summaryrefslogtreecommitdiff
path: root/graphics/asymptote/LspCpp
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-12-28 03:01:00 +0000
committerNorbert Preining <norbert@preining.info>2021-12-28 03:01:00 +0000
commitecdf859b6ce481abfd530425dcf6f0f764bd0001 (patch)
tree13bc161dc046876ac6c92fce5f9f5034ba9aa573 /graphics/asymptote/LspCpp
parent790995b7e79697514364450bf9c04f1b8d500838 (diff)
CTAN sync 202112280300
Diffstat (limited to 'graphics/asymptote/LspCpp')
-rw-r--r--graphics/asymptote/LspCpp/LICENSE21
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/Cancellation.h23
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/Condition.h48
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.cpp35
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.h216
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.cpp46
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.h53
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.cpp17
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.h19
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageIssue.h182
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.cpp57
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.h61
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageProducer.h13
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/NotificationInMessage.h62
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.cpp612
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.h340
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/RequestInMessage.h70
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/ScopeExit.h59
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.cpp191
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.h48
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.cpp299
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.h40
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.cpp341
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.h87
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/json.h81
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsRequestId.h51
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsResponseMessage.h71
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.cpp88
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.h34
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/optional.hpp1846
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.cpp214
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.h378
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/stream.h196
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.cpp20
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.h249
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/JsonRpc/traits.h158
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/AbsolutePath.h27
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ClientPreferences.h306
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/CodeActionParams.h114
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/Directory.h13
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ExecuteCommandParams.h20
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/IProgressMonitor.h145
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.cpp942
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.h119
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/Markup/string_ref.h1059
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.cpp106
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.h17
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ProcessIoService.h48
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.cpp716
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.h11
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/ResourceOperation.h121
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/SimpleTimer.h49
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/client/registerCapability.h49
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/client/unregisterCapability.h41
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/Move.h14
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/OverridableMethod.h34
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h13
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/addOverridableMethods.h19
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/buildWorkspace.h17
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h29
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h29
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h36
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkToStringStatus.h24
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/classFileContents.h10
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/codeActionResult.h22
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/executeCommand.h29
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/findLinks.h22
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateAccessors.h19
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateConstructors.h19
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h25
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h25
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateToString.h18
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getMoveDestinations.h65
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getRefactorEdit.h77
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/listOverridableMethods.h17
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/organizeImports.h12
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h13
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h24
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/searchSymbols.h27
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/SCTConfig.h37
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/protocol.h222
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.cpp743
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.h103
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/extention/sonarlint/protocol.h176
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/InitializeParams.h128
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/exit.h7
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.cpp45
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.h39
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/initialized.h13
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/lsClientCapabilities.h48
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/lsServerCapabilities.h589
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h713
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h256
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/progress.h16
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/general/shutdown.h15
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/language/language.h170
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/location_type.h63
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lru_cache.h151
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsAny.h159
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsCodeAction.h58
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsCommand.h44
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsDocumentUri.h26
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsFormattingOptions.h43
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsMarkedString.h45
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsPosition.h40
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsRange.h32
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsResponseError.h117
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentEdit.h24
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentIdentifier.h14
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentItem.h26
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentPositionParams.h26
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsTextEdit.h87
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h32
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsWorkspaceEdit.h57
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsp.cpp1087
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsp_code_action.h64
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsp_completion.h224
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.cpp74
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.h151
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/method_type.h7
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/out_list.h22
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/symbol.h164
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h267
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/callHierarchy.h121
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_action.h37
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_lens.h42
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/colorPresentation.h63
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/completion.h82
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/declaration_definition.h29
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/didRenameFiles.h44
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_change.h51
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_close.h33
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_open.h39
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_save.h31
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/documentColor.h73
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_link.h44
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_symbol.h55
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/foldingRange.h62
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/formatting.h32
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/highlight.h18
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/hover.h55
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/implementation.h16
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/linkedEditingRange.h51
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/onTypeFormatting.h44
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/prepareRename.h40
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/publishDiagnostics.h28
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/range_formatting.h35
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/references.h48
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/rename.h41
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCodeLens.h10
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCompletionItem.h21
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveTypeHierarchy.h31
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/selectionRange.h52
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/semanticHighlighting.h66
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/signature_help.h92
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/textDocument.cpp349
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/typeHierarchy.h133
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/type_definition.h16
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/willSave.h71
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/utils.cpp602
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/utils.h141
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/windows/MessageNotify.h83
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/working_files.cpp186
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/working_files.h72
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/applyEdit.h42
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/configuration.h37
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h48
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_configuration.h25
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_watched_files.h46
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/execute_command.h24
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/symbol.h16
-rw-r--r--graphics/asymptote/LspCpp/LibLsp/lsp/workspace/workspaceFolders.h34
-rw-r--r--graphics/asymptote/LspCpp/LspCpp.filters465
-rw-r--r--graphics/asymptote/LspCpp/LspCpp.user4
-rw-r--r--graphics/asymptote/LspCpp/LspCpp.vcxproj668
-rw-r--r--graphics/asymptote/LspCpp/LspCpp.vcxproj.filters669
-rw-r--r--graphics/asymptote/LspCpp/LspCpp.vcxproj.user4
-rw-r--r--graphics/asymptote/LspCpp/Makefile40
-rw-r--r--graphics/asymptote/LspCpp/README.md48
-rw-r--r--graphics/asymptote/LspCpp/example/StdIOClientExample.cpp221
-rw-r--r--graphics/asymptote/LspCpp/example/StdIOServerExample.cpp162
-rw-r--r--graphics/asymptote/LspCpp/example/TcpServerExample.cpp200
-rw-r--r--graphics/asymptote/LspCpp/example/WebsocketExample.cpp297
-rw-r--r--graphics/asymptote/LspCpp/macro_map.h134
-rw-r--r--graphics/asymptote/LspCpp/network/optional.hpp711
-rw-r--r--graphics/asymptote/LspCpp/network/string_view.hpp273
-rw-r--r--graphics/asymptote/LspCpp/network/uri.hpp38
-rw-r--r--graphics/asymptote/LspCpp/network/uri/config.hpp20
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/algorithm.hpp73
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/decode.hpp78
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/encode.hpp169
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/grammar.hpp130
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/translate.hpp89
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.cpp76
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.hpp21
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.cpp87
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.hpp20
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_parse.cpp424
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_parse.hpp19
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.cpp130
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.hpp21
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_parts.hpp88
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_percent_encode.hpp80
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.cpp91
-rw-r--r--graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.hpp22
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri.cpp701
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri.hpp758
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri_builder.cpp152
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri_builder.hpp277
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri_errors.cpp72
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri_errors.hpp122
-rw-r--r--graphics/asymptote/LspCpp/network/uri/uri_io.hpp62
-rw-r--r--graphics/asymptote/LspCpp/packages.config14
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG88
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/COPYING5
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v213
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/Jamrules1
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt23
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/Makefile32
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/README10
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/TODO36
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp28
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp215
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp85
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp453
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp65
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp115
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp144
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp232
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp70
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp262
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp83
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp99
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp168
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile36
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt35
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm38
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt14
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm38
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm17
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm17
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm30
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm29
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html9
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt205
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm36
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox220
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm40
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css331
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt207
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm40
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp200
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README7
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp50
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp149
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp263
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam2
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt42
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE23
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/README.md1503
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp64
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h34
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h335
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h338
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h103
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h103
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h274
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt47
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile5
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp59
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp189
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp32
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp109
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp88
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txtbin0 -> 20010 bytes
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp161
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp34
285 files changed, 36840 insertions, 0 deletions
diff --git a/graphics/asymptote/LspCpp/LICENSE b/graphics/asymptote/LspCpp/LICENSE
new file mode 100644
index 0000000000..e2016d4801
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 kuafuwang
+
+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/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Cancellation.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Cancellation.h
new file mode 100644
index 0000000000..b89f32f166
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Cancellation.h
@@ -0,0 +1,23 @@
+#pragma once
+#include <functional>
+#include "lsRequestId.h"
+#include <LibLsp/JsonRpc/NotificationInMessage.h>
+using CancelMonitor = std::function<int()>;
+namespace Cancellation
+{
+
+ struct Params {
+ /**
+ * The request id to cancel.
+ */
+ lsRequestId id;
+
+ MAKE_SWAP_METHOD(Cancellation::Params, id);
+ };
+
+};
+MAKE_REFLECT_STRUCT(Cancellation::Params, id);
+
+DEFINE_NOTIFICATION_TYPE(Notify_Cancellation, Cancellation::Params,"$/cancelRequest");
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Condition.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Condition.h
new file mode 100644
index 0000000000..a5f550041d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Condition.h
@@ -0,0 +1,48 @@
+#pragma once
+#include <condition_variable>
+template <class T>
+class Condition
+{
+public:
+
+ std::mutex m_mutex;
+ std::condition_variable m_condition;
+ ~Condition() {
+ m_condition.notify_all();
+ }
+ void notify(std::unique_ptr<T> data) noexcept
+ {
+ {
+ std::lock_guard<std::mutex> eventLock(m_mutex);
+ any.swap(data);
+ }
+ // wake up one waiter
+ m_condition.notify_one();
+ };
+
+
+ std::unique_ptr<T> wait(unsigned timeout=0)
+ {
+ std::unique_lock<std::mutex> ul(m_mutex);
+ if (!timeout) {
+ m_condition.wait(ul,[&]() {
+ if (!any)
+ return false;
+ return true;
+ });
+ }
+ else{
+ if(!any){
+ std::cv_status status = m_condition.wait_for(ul, std::chrono::milliseconds(timeout));
+ if (status == std::cv_status::timeout)
+ {
+ return {};
+ }
+ }
+ }
+ return std::unique_ptr<T>(any.release());
+
+ }
+private:
+ std::unique_ptr<T> any;
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.cpp
new file mode 100644
index 0000000000..5fb1ad4d45
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.cpp
@@ -0,0 +1,35 @@
+//===--- Context.cpp ---------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Context.h"
+#include <cassert>
+
+namespace lsp {
+
+
+Context Context::empty() { return Context(/*dataPtr=*/nullptr); }
+
+Context::Context(std::shared_ptr<const Data> DataPtr)
+ : dataPtr(std::move(DataPtr)) {}
+
+Context Context::clone() const { return Context(dataPtr); }
+
+static Context &currentContext() {
+ static thread_local auto c = Context::empty();
+ return c;
+}
+
+const Context &Context::current() { return currentContext(); }
+
+Context Context::swapCurrent(Context Replacement) {
+ std::swap(Replacement, currentContext());
+ return Replacement;
+}
+
+
+} // lsp clang
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.h
new file mode 100644
index 0000000000..20edf71b1c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Context.h
@@ -0,0 +1,216 @@
+//===--- Context.h - Mechanism for passing implicit data --------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Context for storing and retrieving implicit data. Useful for passing implicit
+// parameters on a per-request basis.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <memory>
+#include <type_traits>
+
+namespace lsp {
+
+
+/// Values in a Context are indexed by typed keys.
+/// Key<T> serves two purposes:
+/// - it provides a lookup key for the context (each Key is unique),
+/// - it makes lookup type-safe: a Key<T> can only map to a T (or nothing).
+///
+/// Example:
+/// Key<int> RequestID;
+/// Key<int> Version;
+///
+/// Context Ctx = Context::empty().derive(RequestID, 10).derive(Version, 3);
+/// assert(*Ctx.get(RequestID) == 10);
+/// assert(*Ctx.get(Version) == 3);
+///
+/// Keys are typically used across multiple functions, so most of the time you
+/// would want to make them static class members or global variables.
+template <class Type> class Key {
+public:
+ static_assert(!std::is_reference<Type>::value,
+ "Reference arguments to Key<> are not allowed");
+
+ constexpr Key() = default;
+
+ Key(Key const &) = delete;
+ Key &operator=(Key const &) = delete;
+ Key(Key &&) = delete;
+ Key &operator=(Key &&) = delete;
+};
+
+/// A context is an immutable container for per-request data that must be
+/// propagated through layers that don't care about it. An example is a request
+/// ID that we may want to use when logging.
+///
+/// Conceptually, a context is a heterogeneous map<Key<T>, T>. Each key has
+/// an associated value type, which allows the map to be typesafe.
+///
+/// There is an "ambient" context for each thread, Context::current().
+/// Most functions should read from this, and use WithContextValue or
+/// WithContext to extend or replace the context within a block scope.
+/// Only code dealing with threads and extension points should need to use
+/// other Context objects.
+///
+/// You can't add data to an existing context, instead you create a new
+/// immutable context derived from it with extra data added. When you retrieve
+/// data, the context will walk up the parent chain until the key is found.
+class Context {
+public:
+ /// Returns an empty root context that contains no data.
+ static Context empty();
+ /// Returns the context for the current thread, creating it if needed.
+ static const Context &current();
+ // Sets the current() context to Replacement, and returns the old context.
+ // Prefer to use WithContext or WithContextValue to do this safely.
+ static Context swapCurrent(Context Replacement);
+
+private:
+ struct Data;
+ Context(std::shared_ptr<const Data> DataPtr);
+
+public:
+ /// Same as Context::empty(), please use Context::empty() instead.
+ Context() = default;
+
+ /// Copy operations for this class are deleted, use an explicit clone() method
+ /// when you need a copy of the context instead.
+ Context(Context const &) = delete;
+ Context &operator=(const Context &) = delete;
+
+ Context(Context &&) = default;
+ Context &operator=(Context &&) = default;
+
+ /// Get data stored for a typed \p Key. If values are not found
+ /// \returns Pointer to the data associated with \p Key. If no data is
+ /// specified for \p Key, return null.
+ template <class Type> const Type *get(const Key<Type> &Key) const {
+ for (const Data *DataPtr = this->dataPtr.get(); DataPtr != nullptr;
+ DataPtr = DataPtr->parent.get()) {
+ if (DataPtr->KeyPtr == &Key)
+ return static_cast<const Type *>(DataPtr->value->getValuePtr());
+ }
+ return nullptr;
+ }
+
+ /// A helper to get a reference to a \p Key that must exist in the map.
+ /// Must not be called for keys that are not in the map.
+ template <class Type> const Type &getExisting(const Key<Type> &Key) const {
+ auto Val = get(Key);
+ assert(Val && "Key does not exist");
+ return *Val;
+ }
+
+ /// Derives a child context
+ /// It is safe to move or destroy a parent context after calling derive().
+ /// The child will keep its parent alive, and its data remains accessible.
+ template <class Type>
+ Context derive(const Key<Type> &Key,
+ typename std::decay<Type>::type Value) const & {
+ return Context(std::make_shared<Data>(
+ Data{/*parent=*/dataPtr, &Key,
+ std::make_unique<TypedAnyStorage<typename std::decay<Type>::type>>(
+ std::move(Value))}));
+ }
+
+ template <class Type>
+ Context
+ derive(const Key<Type> &Key,
+ typename std::decay<Type>::type Value) && /* takes ownership */ {
+ return Context(std::make_shared<Data>(
+ Data{/*parent=*/std::move(dataPtr), &Key,
+ std::make_unique<TypedAnyStorage<typename std::decay<Type>::type>>(
+ std::move(Value))}));
+ }
+
+ /// Derives a child context, using an anonymous key.
+ /// Intended for objects stored only for their destructor's side-effect.
+ template <class Type> Context derive(Type &&Value) const & {
+ static Key<typename std::decay<Type>::type> Private;
+ return derive(Private, std::forward<Type>(Value));
+ }
+
+ template <class Type> Context derive(Type &&Value) && {
+ static Key<typename std::decay<Type>::type> Private;
+ return std::move(*this).derive(Private, std::forward<Type>(Value));
+ }
+
+ /// Clone this context object.
+ Context clone() const;
+
+private:
+ class AnyStorage {
+ public:
+ virtual ~AnyStorage() = default;
+ virtual void *getValuePtr() = 0;
+ };
+
+ template <class T> class TypedAnyStorage : public Context::AnyStorage {
+ static_assert(std::is_same<typename std::decay<T>::type, T>::value,
+ "Argument to TypedAnyStorage must be decayed");
+
+ public:
+ TypedAnyStorage(T &&Value) : value(std::move(Value)) {}
+
+ void *getValuePtr() override { return &value; }
+
+ private:
+ T value;
+ };
+
+ struct Data {
+ // We need to make sure parent outlives the value, so the order of members
+ // is important. We do that to allow classes stored in Context's child
+ // layers to store references to the data in the parent layers.
+ std::shared_ptr<const Data> parent;
+ const void *KeyPtr;
+ std::unique_ptr<AnyStorage> value;
+ };
+
+ std::shared_ptr<const Data> dataPtr;
+};
+
+/// WithContext replaces Context::current() with a provided scope.
+/// When the WithContext is destroyed, the original scope is restored.
+/// For extending the current context with new value, prefer WithContextValue.
+class WithContext {
+public:
+ WithContext(Context C) : restore(Context::swapCurrent(std::move(C))) {}
+ ~WithContext() { Context::swapCurrent(std::move(restore)); }
+ WithContext(const WithContext &) = delete;
+ WithContext &operator=(const WithContext &) = delete;
+ WithContext(WithContext &&) = delete;
+ WithContext &operator=(WithContext &&) = delete;
+
+private:
+ Context restore;
+};
+
+/// WithContextValue extends Context::current() with a single value.
+/// When the WithContextValue is destroyed, the original scope is restored.
+class WithContextValue {
+public:
+ template <typename T>
+ WithContextValue(const Key<T> &K, typename std::decay<T>::type V)
+ : restore(Context::current().derive(K, std::move(V))) {}
+
+ // Anonymous values can be used for the destructor side-effect.
+ template <typename T>
+ WithContextValue(T &&V)
+ : restore(Context::current().derive(std::forward<T>(V))) {}
+
+private:
+ WithContext restore;
+};
+
+
+} // namespace lsp
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.cpp
new file mode 100644
index 0000000000..549744555b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.cpp
@@ -0,0 +1,46 @@
+#include "Endpoint.h"
+#include "message.h"
+
+
+bool GenericEndpoint::notify(std::unique_ptr<LspMessage> msg)
+{
+ auto findIt = method2notification.find(msg->GetMethodType());
+
+ if (findIt != method2notification.end())
+ {
+ return findIt->second(std::move(msg));
+ }
+ std::string info = "can't find method2notification for notification:\n" + msg->ToJson() + "\n";
+ log.log(lsp::Log::Level::SEVERE, info);
+ return false;
+}
+
+bool GenericEndpoint::onResponse(const std::string& method, std::unique_ptr<LspMessage>msg)
+{
+ auto findIt = method2response.find(method);
+
+ if (findIt != method2response.end())
+ {
+ return findIt->second(std::move(msg));
+ }
+
+ std::string info = "can't find method2response for response:\n" + msg->ToJson() + "\n";
+ log.log(lsp::Log::Level::SEVERE, info);
+
+ return false;
+}
+
+
+
+bool GenericEndpoint::onRequest(std::unique_ptr<LspMessage> request)
+{
+ auto findIt = method2request.find(request->GetMethodType());
+
+ if (findIt != method2request.end())
+ {
+ return findIt->second(std::move(request));
+ }
+ std::string info = "can't find method2request for request:\n" + request->ToJson() + "\n";
+ log.log(lsp::Log::Level::SEVERE, info);
+ return false;
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.h
new file mode 100644
index 0000000000..01d8e8ca91
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/Endpoint.h
@@ -0,0 +1,53 @@
+#pragma once
+#include <map>
+#include <functional>
+#include <memory>
+#include "MessageIssue.h"
+struct LspMessage;
+struct NotificationInMessage;
+struct lsBaseOutMessage;
+struct RequestInMessage;
+
+using GenericResponseHandler = std::function< bool(std::unique_ptr<LspMessage>) >;
+using GenericRequestHandler = std::function< bool(std::unique_ptr<LspMessage>) >;
+using GenericNotificationHandler = std::function< bool(std::unique_ptr<LspMessage>) >;
+
+class Endpoint
+{
+public:
+ virtual ~Endpoint() = default;
+ virtual bool onRequest(std::unique_ptr<LspMessage>) = 0;
+ virtual bool notify(std::unique_ptr<LspMessage>) = 0;
+
+ virtual bool onResponse(const std::string&, std::unique_ptr<LspMessage>) = 0;
+ virtual void registerRequestHandler(const std::string&, GenericResponseHandler ) = 0;
+ virtual void registerNotifyHandler(const std::string&, GenericNotificationHandler ) = 0;
+};
+
+class GenericEndpoint :public Endpoint
+{
+
+public:
+ GenericEndpoint(lsp::Log& l):log(l){}
+ bool notify(std::unique_ptr<LspMessage>) override;
+ bool onResponse(const std::string&, std::unique_ptr<LspMessage>) override;
+
+ bool onRequest(std::unique_ptr<LspMessage>) override;
+ std::map< std::string, GenericRequestHandler > method2request;
+ std::map< std::string, GenericResponseHandler > method2response;
+ std::map< std::string, GenericNotificationHandler > method2notification;
+
+ void registerRequestHandler(const std::string& method, GenericResponseHandler cb) override
+ {
+ method2request[method] = cb;
+ }
+
+ void registerNotifyHandler(const std::string& method, GenericNotificationHandler cb) override
+ {
+ method2notification[method] = cb;
+ }
+ lsp::Log& log;
+
+
+
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.cpp
new file mode 100644
index 0000000000..15253411a1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.cpp
@@ -0,0 +1,17 @@
+#include "GCThreadContext.h"
+#include <iostream>
+
+GCThreadContext::GCThreadContext()
+{
+#ifdef USEGC
+ GC_get_stack_base(&gsb);
+ GC_register_my_thread(&gsb);
+#endif
+}
+
+GCThreadContext::~GCThreadContext()
+{
+#ifdef USEGC
+ GC_unregister_my_thread();
+#endif
+} \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.h
new file mode 100644
index 0000000000..a0f7db288d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/GCThreadContext.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#if defined(USEGC)
+#define GC_THREADS
+#include <gc.h>
+#endif
+
+class GCThreadContext
+{
+public:
+ GCThreadContext();
+ ~GCThreadContext();
+
+private:
+#if defined(USEGC)
+ GC_stack_base gsb;
+#endif
+
+}; \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageIssue.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageIssue.h
new file mode 100644
index 0000000000..bda6e65d46
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageIssue.h
@@ -0,0 +1,182 @@
+#pragma once
+#include <string>
+#include <functional>
+#include <vector>
+namespace lsp
+{
+ class Log
+ {
+ public:
+ virtual ~Log() = default;
+
+ enum class Level
+ {
+ /**
+ * OFF is a special level that can be used to turn off logging.
+
+ */
+ OFF = 1,
+
+ /**
+ * SEVERE is a message level indicating a serious failure.
+ * <p>
+ * In general SEVERE messages should describe events that are
+ * of considerable importance and which will prevent normal
+ * program execution. They should be reasonably intelligible
+ * to end users and to system administrators.
+
+ */
+ SEVERE = 2,
+
+ /**
+ * WARNING is a message level indicating a potential problem.
+ * <p>
+ * In general WARNING messages should describe events that will
+ * be of interest to end users or system managers, or which
+ * indicate potential problems.
+
+ *
+ */
+ WARNING = 3,
+ /**
+ * INFO is a message level for informational messages.
+ * <p>
+ * Typically INFO messages will be written to the console
+ * or its equivalent. So the INFO level should only be
+ * used for reasonably significant messages that will
+ * make sense to end users and system administrators.
+
+ */
+ INFO = 3,
+ /**
+ * CONFIG is a message level for static configuration messages.
+ * <p>
+ * CONFIG messages are intended to provide a variety of static
+ * configuration information, to assist in debugging problems
+ * that may be associated with particular configurations.
+ * For example, CONFIG message might include the CPU type,
+ * the graphics depth, the GUI look-and-feel, etc.
+ * This level is initialized to <CODE>4</CODE>.
+ */
+
+ CONFIG = 4,
+
+
+
+ /**
+ * FINE is a message level providing tracing information.
+ * <p>
+ * All of FINE, FINER, and FINEST are intended for relatively
+ * detailed tracing. The exact meaning of the three levels will
+ * vary between subsystems, but in general, FINEST should be used
+ * for the most voluminous detailed output, FINER for somewhat
+ * less detailed output, and FINE for the lowest volume (and
+ * most important) messages.
+ * <p>
+ * In general the FINE level should be used for information
+ * that will be broadly interesting to developers who do not have
+ * a specialized interest in the specific subsystem.
+ * <p>
+ * FINE messages might include things like minor (recoverable)
+ * failures. Issues indicating potential performance problems
+ * are also worth logging as FINE.
+ * This level is initialized to <CODE>5</CODE>.
+ */
+ FINE = 5,
+
+ /**
+ * FINER indicates a fairly detailed tracing message.
+ * By default logging calls for entering, returning, or throwing
+ * an exception are traced at this level.
+ * This level is initialized to <CODE>400</CODE>.
+ */
+ FINER = 6,
+
+ /**
+ * FINEST indicates a highly detailed tracing message.
+ * This level is initialized to <CODE>300</CODE>.
+ */
+ FINEST = 7,
+
+ /**
+ * ALL indicates that all messages should be logged.
+ * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>.
+ */
+ ALL,
+ };
+ virtual void log(Level level, std::wstring&& msg) = 0;
+ virtual void log(Level level, const std::wstring& msg) = 0;
+ virtual void log(Level level, std::string&& msg) = 0;
+ virtual void log(Level level, const std::string& msg) = 0;
+
+ void info(const std::string& msg)
+ {
+ log(Level::INFO, msg);
+ }
+ void info(const std::wstring& msg)
+ {
+ log(Level::INFO, msg);
+ }
+ void error(const std::string& msg)
+ {
+ log(Level::SEVERE, msg);
+ }
+ void error(const std::wstring& msg)
+ {
+ log(Level::SEVERE, msg);
+ }
+ void warning(const std::string& msg)
+ {
+ log(Level::WARNING, msg);
+ }
+ void warning(const std::wstring& msg)
+ {
+ log(Level::WARNING, msg);
+ }
+ };
+}
+
+class MessageIssue {
+
+public:
+ std::string text;
+
+ lsp::Log::Level code;
+
+ MessageIssue(const std::string& text, lsp::Log::Level code) :text(text), code(code)
+ {
+
+
+ }
+ MessageIssue(std::string&& text, lsp::Log::Level code) :text(text), code(code)
+ {
+
+
+ }
+
+
+ std::string getText() {
+ return text;
+ }
+
+ lsp::Log::Level getIssueCode() {
+ return code;
+ }
+
+
+ std::string toString() {
+ return getText();
+ }
+
+};
+class MessageIssueHandler
+{
+public:
+ /**
+ * Handle issues found while parsing or validating a message. The list of issues must not be empty.
+ */
+ virtual ~MessageIssueHandler() = default;
+
+ virtual void handle(std::vector<MessageIssue>&&) = 0;
+ virtual void handle( MessageIssue&&) = 0;
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.cpp
new file mode 100644
index 0000000000..111b29aa1c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.cpp
@@ -0,0 +1,57 @@
+#include "MessageJsonHandler.h"
+#include <string>
+#include <rapidjson/document.h>
+
+
+
+std::unique_ptr<LspMessage> MessageJsonHandler::parseResponseMessage(const std::string& method, Reader& r)
+{
+ auto findIt = method2response.find(method);
+
+ if( findIt != method2response.end())
+ {
+ return findIt->second(r);
+ }
+ return nullptr;
+}
+
+std::unique_ptr<LspMessage> MessageJsonHandler::parseRequstMessage(const std::string& method, Reader&r)
+{
+ auto findIt = method2request.find(method);
+
+ if (findIt != method2request.end())
+ {
+ return findIt->second(r);
+ }
+ return nullptr;
+}
+
+bool MessageJsonHandler::resovleResponseMessage(Reader&r, std::pair<std::string, std::unique_ptr<LspMessage>>& result)
+{
+ for (auto& handler : method2response)
+ {
+ try
+ {
+ auto msg = handler.second(r);
+ result.first = handler.first;
+ result.second = std::move(msg);
+ return true;
+ }
+ catch (...)
+ {
+
+ }
+ }
+ return false;
+}
+
+std::unique_ptr<LspMessage> MessageJsonHandler::parseNotificationMessage(const std::string& method, Reader& r)
+{
+ auto findIt = method2notification.find(method);
+
+ if (findIt != method2notification.end())
+ {
+ return findIt->second(r);
+ }
+ return nullptr;
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.h
new file mode 100644
index 0000000000..7e238b0cf6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageJsonHandler.h
@@ -0,0 +1,61 @@
+#pragma once
+#include <string>
+#include <map>
+#include <functional>
+#include <LibLsp/JsonRpc/message.h>
+class Reader;
+
+
+using GenericRequestJsonHandler = std::function< std::unique_ptr<LspMessage>(Reader&) >;
+using GenericResponseJsonHandler = std::function< std::unique_ptr<LspMessage>(Reader&) >;
+using GenericNotificationJsonHandler = std::function< std::unique_ptr<LspMessage>(Reader&) >;
+
+class MessageJsonHandler
+{
+public:
+ std::map< std::string, GenericRequestJsonHandler > method2request;
+ std::map< std::string, GenericResponseJsonHandler > method2response;
+ std::map< std::string, GenericNotificationJsonHandler > method2notification;
+
+
+ const GenericRequestJsonHandler* GetRequestJsonHandler(const char* methodInfo) const
+ {
+ const auto findIt = method2request.find(methodInfo);
+ return findIt == method2request.end() ? nullptr : &findIt->second;
+ }
+
+ void SetRequestJsonHandler(const std::string& methodInfo, GenericRequestJsonHandler handler)
+ {
+ method2request[methodInfo] = handler;
+ }
+
+ const GenericResponseJsonHandler* GetResponseJsonHandler(const char* methodInfo) const
+ {
+ const auto findIt = method2response.find(methodInfo);
+ return findIt == method2response.end() ? nullptr : &findIt->second;
+ }
+
+ void SetResponseJsonHandler(const std::string& methodInfo,GenericResponseJsonHandler handler)
+ {
+ method2response[methodInfo] = handler;
+ }
+
+ const GenericNotificationJsonHandler* GetNotificationJsonHandler(const char* methodInfo) const
+ {
+ const auto findIt = method2notification.find(methodInfo);
+ return findIt == method2notification.end() ? nullptr : &findIt->second;
+ }
+
+ void SetNotificationJsonHandler(const std::string& methodInfo, GenericNotificationJsonHandler handler)
+ {
+ method2notification[methodInfo] = handler;
+ }
+
+
+
+ std::unique_ptr<LspMessage> parseResponseMessage(const std::string&, Reader&);
+ std::unique_ptr<LspMessage> parseRequstMessage(const std::string&, Reader&);
+ bool resovleResponseMessage(Reader&, std::pair<std::string, std::unique_ptr<LspMessage>>& result);
+ std::unique_ptr<LspMessage> parseNotificationMessage(const std::string&, Reader&);
+};
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageProducer.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageProducer.h
new file mode 100644
index 0000000000..ab7a29a17f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/MessageProducer.h
@@ -0,0 +1,13 @@
+#pragma once
+#include <string>
+#include <functional>
+
+class MessageProducer
+{
+public:
+
+
+ typedef std::function< void(std::string&&) > MessageConsumer;
+ virtual ~MessageProducer() = default;
+ virtual void listen(MessageConsumer) = 0;
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/NotificationInMessage.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/NotificationInMessage.h
new file mode 100644
index 0000000000..e4841b5703
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/NotificationInMessage.h
@@ -0,0 +1,62 @@
+#pragma once
+
+
+#include "lsRequestId.h"
+#include "LibLsp/JsonRpc/message.h"
+
+
+
+// NotificationInMessage does not have |id|.
+struct NotificationInMessage : public LspMessage {
+
+ Kind GetKid() override
+ {
+ return NOTIFICATION_MESSAGE;
+ }
+ MethodType GetMethodType() const override
+ {
+ return method.c_str();
+ }
+ void SetMethodType(MethodType _t) override
+ {
+ method = _t;
+ }
+ std::string method;
+};
+template <class T, class TDerived >
+struct lsNotificationInMessage : NotificationInMessage {
+
+ void ReflectWriter(Writer& writer) override {
+ Reflect(writer, static_cast<TDerived&>(*this));
+ }
+ lsNotificationInMessage(MethodType _method)
+ {
+ method = _method;
+ }
+
+ static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) {
+
+ TDerived* temp = new TDerived();
+
+ std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp);
+ // Reflect may throw and *message will be partially deserialized.
+ Reflect(visitor, static_cast<TDerived&>(*temp));
+ return message;
+
+ }
+ void swap(lsNotificationInMessage& arg) noexcept
+ {
+ method.swap(method);
+ std::swap(params, arg.params);
+ }
+ T params;
+};
+
+#define DEFINE_NOTIFICATION_TYPE(MSG,paramType,methodInfo)\
+namespace MSG {\
+ struct notify : public lsNotificationInMessage< paramType , notify >{\
+ static constexpr MethodType kMethodInfo = methodInfo;\
+ notify():lsNotificationInMessage(kMethodInfo){} \
+ };\
+};\
+MAKE_REFLECT_STRUCT(MSG::notify, jsonrpc,method, params)
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.cpp
new file mode 100644
index 0000000000..46f09ec686
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.cpp
@@ -0,0 +1,612 @@
+#include "MessageJsonHandler.h"
+#include "Endpoint.h"
+#include "message.h"
+#include "RemoteEndPoint.h"
+#include <future>
+#include "Cancellation.h"
+#include "StreamMessageProducer.h"
+#include "NotificationInMessage.h"
+#include "lsResponseMessage.h"
+#include "Condition.h"
+#include "Context.h"
+#include "rapidjson/error/en.h"
+#include "json.h"
+#include "GCThreadContext.h"
+#include "ScopeExit.h"
+#include "stream.h"
+
+#define BOOST_BIND_GLOBAL_PLACEHOLDERS
+#include "boost/threadpool.hpp"
+#include <atomic>
+namespace lsp {
+
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//===----------------------------------------------------------------------===//
+
+// Cancellation mechanism for long-running tasks.
+//
+// This manages interactions between:
+//
+// 1. Client code that starts some long-running work, and maybe cancels later.
+//
+// std::pair<Context, Canceler> Task = cancelableTask();
+// {
+// WithContext Cancelable(std::move(Task.first));
+// Expected
+// deepThoughtAsync([](int answer){ errs() << answer; });
+// }
+// // ...some time later...
+// if (User.fellAsleep())
+// Task.second();
+//
+// (This example has an asynchronous computation, but synchronous examples
+// work similarly - the Canceler should be invoked from another thread).
+//
+// 2. Library code that executes long-running work, and can exit early if the
+// result is not needed.
+//
+// void deepThoughtAsync(std::function<void(int)> Callback) {
+// runAsync([Callback]{
+// int A = ponder(6);
+// if (getCancelledMonitor())
+// return;
+// int B = ponder(9);
+// if (getCancelledMonitor())
+// return;
+// Callback(A * B);
+// });
+// }
+//
+// (A real example may invoke the callback with an error on cancellation,
+// the CancelledError is provided for this purpose).
+//
+// Cancellation has some caveats:
+// - the work will only stop when/if the library code next checks for it.
+// Code outside clangd such as Sema will not do this.
+// - it's inherently racy: client code must be prepared to accept results
+// even after requesting cancellation.
+// - it's Context-based, so async work must be dispatched to threads in
+// ways that preserve the context. (Like runAsync() or TUScheduler).
+//
+
+ /// A canceller requests cancellation of a task, when called.
+ /// Calling it again has no effect.
+ using Canceler = std::function<void()>;
+
+ // We don't want a cancelable scope to "shadow" an enclosing one.
+ struct CancelState {
+ std::shared_ptr<std::atomic<int>> cancelled;
+ const CancelState* parent = nullptr;
+ lsRequestId id;
+ };
+ static Key<CancelState> g_stateKey;
+
+ /// Defines a new task whose cancellation may be requested.
+ /// The returned Context defines the scope of the task.
+ /// When the context is active, getCancelledMonitor() is 0 until the Canceler is
+ /// invoked, and equal to Reason afterwards.
+ /// Conventionally, Reason may be the LSP error code to return.
+ std::pair<Context, Canceler> cancelableTask(const lsRequestId& id,int reason = 1){
+ assert(reason != 0 && "Can't detect cancellation if Reason is zero");
+ CancelState state;
+ state.id = id;
+ state.cancelled = std::make_shared<std::atomic<int>>();
+ state.parent = Context::current().get(g_stateKey);
+ return {
+ Context::current().derive(g_stateKey, state),
+ [reason, cancelled(state.cancelled)] { *cancelled = reason; },
+ };
+ }
+ /// If the current context is within a cancelled task, returns the reason.
+/// (If the context is within multiple nested tasks, true if any are cancelled).
+/// Always zero if there is no active cancelable task.
+/// This isn't free (context lookup) - don't call it in a tight loop.
+ boost::optional<CancelMonitor> getCancelledMonitor(const lsRequestId& id, const Context& ctx = Context::current()){
+ for (const CancelState* state = ctx.get(g_stateKey); state != nullptr;
+ state = state->parent)
+ {
+ if (id != state->id)continue;
+ const std::shared_ptr<std::atomic<int> > cancelled = state->cancelled;
+ std::function<int()> temp = [=]{
+ return cancelled->load();
+ };
+ return std::move(temp);
+ }
+
+ return {};
+ }
+} // namespace lsp
+
+using namespace lsp;
+class PendingRequestInfo
+{
+ using RequestCallBack = std::function< bool(std::unique_ptr<LspMessage>) >;
+public:
+ PendingRequestInfo(const std::string& md,
+ const RequestCallBack& callback);
+ PendingRequestInfo(const std::string& md);
+ PendingRequestInfo() {}
+ std::string method;
+ RequestCallBack futureInfo;
+};
+
+PendingRequestInfo::PendingRequestInfo(const std::string& _md,
+ const RequestCallBack& callback) : method(_md),
+ futureInfo(callback)
+{
+}
+
+PendingRequestInfo::PendingRequestInfo(const std::string& md) : method(md)
+{
+}
+struct RemoteEndPoint::Data
+{
+ explicit Data(lsp::Log& _log , RemoteEndPoint* owner)
+ : m_id(0), next_request_cookie(0), message_producer(new StreamMessageProducer(*owner)), log(_log)
+ {
+
+ }
+ ~Data()
+ {
+ delete message_producer;
+ }
+ std::atomic<unsigned> m_id;
+ boost::threadpool::pool tp;
+ // Method calls may be cancelled by ID, so keep track of their state.
+ // This needs a mutex: handlers may finish on a different thread, and that's
+ // when we clean up entries in the map.
+ mutable std::mutex request_cancelers_mutex;
+
+ std::map< lsRequestId, std::pair<Canceler, /*Cookie*/ unsigned> > requestCancelers;
+
+ std::atomic<unsigned> next_request_cookie; // To disambiguate reused IDs, see below.
+ void onCancel(Notify_Cancellation::notify* notify) {
+ std::lock_guard<std::mutex> Lock(request_cancelers_mutex);
+ const auto it = requestCancelers.find(notify->params.id);
+ if (it != requestCancelers.end())
+ it->second.first(); // Invoke the canceler.
+ }
+
+ // We run cancelable requests in a context that does two things:
+ // - allows cancellation using requestCancelers[ID]
+ // - cleans up the entry in requestCancelers when it's no longer needed
+ // If a client reuses an ID, the last wins and the first cannot be canceled.
+ Context cancelableRequestContext(lsRequestId id) {
+ auto task = cancelableTask(id,
+ /*Reason=*/static_cast<int>(lsErrorCodes::RequestCancelled));
+ unsigned cookie;
+ {
+ std::lock_guard<std::mutex> Lock(request_cancelers_mutex);
+ cookie = next_request_cookie.fetch_add(1, std::memory_order_relaxed);
+ requestCancelers[id] = { std::move(task.second), cookie };
+ }
+ // When the request ends, we can clean up the entry we just added.
+ // The cookie lets us check that it hasn't been overwritten due to ID
+ // reuse.
+ return task.first.derive(lsp::make_scope_exit([this, id, cookie] {
+ std::lock_guard<std::mutex> lock(request_cancelers_mutex);
+ const auto& it = requestCancelers.find(id);
+ if (it != requestCancelers.end() && it->second.second == cookie)
+ requestCancelers.erase(it);
+ }));
+ }
+
+ std::map <lsRequestId, std::shared_ptr<PendingRequestInfo>> _client_request_futures;
+ StreamMessageProducer* message_producer;
+ std::atomic<bool> quit{};
+ lsp::Log& log;
+ std::shared_ptr<lsp::istream> input;
+ std::shared_ptr<lsp::ostream> output;
+
+ void pendingRequest(RequestInMessage& info, GenericResponseHandler&& handler)
+ {
+ auto id = m_id.fetch_add(1, std::memory_order_relaxed);
+ info.id.set(id);
+ std::lock_guard<std::mutex> lock(m_requsetInfo);
+ _client_request_futures[info.id] = std::make_shared<PendingRequestInfo>(info.method, handler);
+
+ }
+ const std::shared_ptr<const PendingRequestInfo> getRequestInfo(const lsRequestId& _id)
+ {
+ std::lock_guard<std::mutex> lock(m_requsetInfo);
+ auto findIt = _client_request_futures.find(_id);
+ if (findIt != _client_request_futures.end())
+ {
+ return findIt->second;
+ }
+ return nullptr;
+ }
+
+ std::mutex m_requsetInfo;
+ void removeRequestInfo(const lsRequestId& _id)
+ {
+ std::lock_guard<std::mutex> lock(m_requsetInfo);
+ auto findIt = _client_request_futures.find(_id);
+ if (findIt != _client_request_futures.end())
+ {
+ _client_request_futures.erase(findIt);
+ }
+ }
+ void clear()
+ {
+ {
+ std::lock_guard<std::mutex> lock(m_requsetInfo);
+ _client_request_futures.clear();
+
+ }
+ tp.clear();
+ quit.store(true, std::memory_order_relaxed);
+ }
+};
+
+namespace
+{
+void WriterMsg(std::shared_ptr<lsp::ostream>& output, LspMessage& msg)
+{
+ const auto& s = msg.ToJson();
+ const auto value =
+ std::string("Content-Length: ") + std::to_string(s.size()) + "\r\n\r\n" + s;
+ output->write(value);
+ output->flush();
+}
+
+bool isResponseMessage(JsonReader& visitor)
+{
+
+ if (!visitor.HasMember("id"))
+ {
+ return false;
+ }
+
+ if (!visitor.HasMember("result") && !visitor.HasMember("error"))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool isRequestMessage(JsonReader& visitor)
+{
+ if (!visitor.HasMember("method"))
+ {
+ return false;
+ }
+ if (!visitor["method"]->IsString())
+ {
+ return false;
+ }
+ if (!visitor.HasMember("id"))
+ {
+ return false;
+ }
+ return true;
+}
+bool isNotificationMessage(JsonReader& visitor)
+{
+ if (!visitor.HasMember("method"))
+ {
+ return false;
+ }
+ if (!visitor["method"]->IsString())
+ {
+ return false;
+ }
+ if (visitor.HasMember("id"))
+ {
+ return false;
+ }
+ return true;
+}
+}
+
+CancelMonitor RemoteEndPoint::getCancelMonitor(const lsRequestId& id)
+{
+ auto monitor = getCancelledMonitor(id);
+ if(monitor.has_value())
+ {
+ return monitor.value();
+ }
+ return [] {
+ return 0;
+ };
+
+}
+
+RemoteEndPoint::RemoteEndPoint(
+ const std::shared_ptr < MessageJsonHandler >& json_handler,const std::shared_ptr < Endpoint>& localEndPoint, lsp::Log& _log, uint8_t max_workers):
+ d_ptr(new Data(_log,this)),jsonHandler(json_handler), local_endpoint(localEndPoint)
+{
+ jsonHandler->method2notification[Notify_Cancellation::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_Cancellation::notify::ReflectReader(visitor);
+ };
+
+ d_ptr->quit.store(false, std::memory_order_relaxed);
+ d_ptr->tp.size_controller().resize(max_workers);
+}
+
+RemoteEndPoint::~RemoteEndPoint()
+{
+ delete d_ptr;
+ d_ptr->quit.store(true, std::memory_order_relaxed);
+}
+
+bool RemoteEndPoint::dispatch(const std::string& content)
+{
+ rapidjson::Document document;
+ document.Parse(content.c_str(), content.length());
+ if (document.HasParseError())
+ {
+ std::string info ="lsp msg format error:";
+ rapidjson::GetParseErrorFunc GetParseError = rapidjson::GetParseError_En; // or whatever
+ info+= GetParseError(document.GetParseError());
+ info += "\n";
+ info += "ErrorContext offset:\n";
+ info += content.substr(document.GetErrorOffset());
+ d_ptr->log.log(Log::Level::SEVERE, info);
+
+ return false;
+ }
+
+ JsonReader visitor{ &document };
+ if (!visitor.HasMember("jsonrpc") ||
+ std::string(visitor["jsonrpc"]->GetString()) != "2.0")
+ {
+ std::string reason;
+ reason = "Reason:Bad or missing jsonrpc version\n";
+ reason += "content:\n" + content;
+ d_ptr->log.log(Log::Level::SEVERE, reason);
+ return false;
+
+ }
+ LspMessage::Kind _kind = LspMessage::NOTIFICATION_MESSAGE;
+ try {
+ if (isRequestMessage(visitor))
+ {
+ _kind = LspMessage::REQUEST_MESSAGE;
+ auto msg = jsonHandler->parseRequstMessage(visitor["method"]->GetString(), visitor);
+ if (msg) {
+ mainLoop(std::move(msg));
+ }
+ else {
+ std::string info = "Unknown support request message when consumer message:\n";
+ info += content;
+ d_ptr->log.log(Log::Level::WARNING, info);
+ return false;
+ }
+ }
+ else if (isResponseMessage(visitor))
+ {
+ _kind = LspMessage::RESPONCE_MESSAGE;
+ lsRequestId id;
+ ReflectMember(visitor, "id", id);
+
+ auto msgInfo = d_ptr->getRequestInfo(id);
+ if (!msgInfo)
+ {
+ std::pair<std::string, std::unique_ptr<LspMessage>> result;
+ auto b = jsonHandler->resovleResponseMessage(visitor, result);
+ if (b)
+ {
+ result.second->SetMethodType(result.first.c_str());
+ mainLoop(std::move(result.second));
+ }
+ else
+ {
+ std::string info = "Unknown response message :\n";
+ info += content;
+ d_ptr->log.log(Log::Level::INFO, info);
+ }
+ }
+ else
+ {
+
+ auto msg = jsonHandler->parseResponseMessage(msgInfo->method, visitor);
+ if (msg) {
+ mainLoop(std::move(msg));
+ }
+ else
+ {
+ std::string info = "Unknown response message :\n";
+ info += content;
+ d_ptr->log.log(Log::Level::SEVERE, info);
+ return false;
+ }
+
+ }
+ }
+ else if (isNotificationMessage(visitor))
+ {
+ auto msg = jsonHandler->parseNotificationMessage(visitor["method"]->GetString(), visitor);
+ if (!msg)
+ {
+ std::string info = "Unknown notification message :\n";
+ info += content;
+ d_ptr->log.log(Log::Level::SEVERE, info);
+ return false;
+ }
+ mainLoop(std::move(msg));
+ }
+ else
+ {
+ std::string info = "Unknown lsp message when consumer message:\n";
+ info += content;
+ d_ptr->log.log(Log::Level::WARNING, info);
+ return false;
+ }
+ }
+ catch (std::exception& e)
+ {
+
+ std::string info = "Exception when process ";
+ if(_kind==LspMessage::REQUEST_MESSAGE)
+ {
+ info += "request";
+ }
+ if (_kind == LspMessage::RESPONCE_MESSAGE)
+ {
+ info += "response";
+ }
+ else
+ {
+ info += "notification";
+ }
+ info += " message:\n";
+ info += e.what();
+ std::string reason = "Reason:" + info + "\n";
+ reason += "content:\n" + content;
+ d_ptr->log.log(Log::Level::SEVERE, reason);
+ return false;
+ }
+ return true;
+}
+
+
+
+void RemoteEndPoint::internalSendRequest( RequestInMessage& info, GenericResponseHandler handler)
+{
+ std::lock_guard<std::mutex> lock(m_sendMutex);
+ if (!d_ptr->output || d_ptr->output->bad())
+ {
+ std::string desc = "Output isn't good any more:\n";
+ d_ptr->log.log(Log::Level::INFO, desc);
+ return ;
+ }
+ d_ptr->pendingRequest(info, std::move(handler));
+ WriterMsg(d_ptr->output, info);
+}
+
+
+std::unique_ptr<LspMessage> RemoteEndPoint::internalWaitResponse(RequestInMessage& request, unsigned time_out)
+{
+ auto eventFuture = std::make_shared< Condition< LspMessage > >();
+ internalSendRequest(request, [=](std::unique_ptr<LspMessage> data)
+ {
+ eventFuture->notify(std::move(data));
+ return true;
+ });
+ return eventFuture->wait(time_out);
+}
+
+void RemoteEndPoint::mainLoop(std::unique_ptr<LspMessage>msg)
+{
+ if(d_ptr->quit.load(std::memory_order_relaxed))
+ {
+ return;
+ }
+ const auto _kind = msg->GetKid();
+ if (_kind == LspMessage::REQUEST_MESSAGE)
+ {
+ auto req = static_cast<RequestInMessage*>(msg.get());
+ // Calls can be canceled by the client. Add cancellation context.
+ WithContext WithCancel(d_ptr->cancelableRequestContext(req->id));
+ local_endpoint->onRequest(std::move(msg));
+ }
+
+ else if (_kind == LspMessage::RESPONCE_MESSAGE)
+ {
+ auto response = static_cast<ResponseInMessage*>(msg.get());
+ auto msgInfo = d_ptr->getRequestInfo(response->id);
+ if (!msgInfo)
+ {
+ const auto _method_desc = msg->GetMethodType();
+ local_endpoint->onResponse(_method_desc, std::move(msg));
+ }
+ else
+ {
+ bool needLocal = true;
+ if (msgInfo->futureInfo)
+ {
+ if (msgInfo->futureInfo(std::move(msg)))
+ {
+ needLocal = false;
+ }
+ }
+ if (needLocal)
+ {
+ local_endpoint->onResponse(msgInfo->method, std::move(msg));
+ }
+ d_ptr->removeRequestInfo(response->id);
+ }
+ }
+ else if (_kind == LspMessage::NOTIFICATION_MESSAGE)
+ {
+ if (strcmp(Notify_Cancellation::notify::kMethodInfo, msg->GetMethodType())==0)
+ {
+ d_ptr->onCancel(static_cast<Notify_Cancellation::notify*>(msg.get()));
+ }
+ else
+ {
+ local_endpoint->notify(std::move(msg));
+ }
+
+ }
+ else
+ {
+ std::string info = "Unknown lsp message when process message in mainLoop:\n";
+ d_ptr->log.log(Log::Level::WARNING, info);
+ }
+}
+
+void RemoteEndPoint::handle(std::vector<MessageIssue>&& issue)
+{
+ for(auto& it : issue)
+ {
+ d_ptr->log.log(it.code, it.text);
+ }
+}
+
+void RemoteEndPoint::handle(MessageIssue&& issue)
+{
+ d_ptr->log.log(issue.code, issue.text);
+}
+
+
+void RemoteEndPoint::startProcessingMessages(std::shared_ptr<lsp::istream> r,
+ std::shared_ptr<lsp::ostream> w)
+{
+ d_ptr->quit.store(false, std::memory_order_relaxed);
+ d_ptr->input = r;
+ d_ptr->output = w;
+ d_ptr->message_producer->bind(r);
+ message_producer_thread_ = std::make_shared<std::thread>([&]()
+ {
+ d_ptr->message_producer->listen([&](std::string&& content){
+ const auto temp = std::make_shared<std::string>(std::move(content));
+ d_ptr->tp.schedule([this, temp]{
+#ifdef USEGC
+ GCThreadContext gcContext;
+#endif
+
+ dispatch(*temp);
+ });
+ });
+ });
+}
+
+void RemoteEndPoint::Stop()
+{
+ if(message_producer_thread_ && message_producer_thread_->joinable())
+ {
+ message_producer_thread_->detach();
+ }
+ d_ptr->clear();
+
+}
+
+void RemoteEndPoint::sendMsg( LspMessage& msg)
+{
+
+ std::lock_guard<std::mutex> lock(m_sendMutex);
+ if (!d_ptr->output || d_ptr->output->bad())
+ {
+ std::string info = "Output isn't good any more:\n";
+ d_ptr->log.log(Log::Level::INFO, info);
+ return;
+ }
+ WriterMsg(d_ptr->output, msg);
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.h
new file mode 100644
index 0000000000..3ae6b567a5
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RemoteEndPoint.h
@@ -0,0 +1,340 @@
+#pragma once
+#include "LibLsp/lsp/lsp_diagnostic.h"
+#include "LibLsp/JsonRpc/Cancellation.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "traits.h"
+#include <future>
+#include <string>
+#include "threaded_queue.h"
+#include <unordered_map>
+#include "MessageIssue.h"
+#include "LibLsp/JsonRpc/MessageJsonHandler.h"
+#include "Endpoint.h"
+
+
+class MessageJsonHandler;
+class Endpoint;
+struct LspMessage;
+class RemoteEndPoint;
+namespace lsp {
+ class ostream;
+ class istream;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // ResponseOrError<T>
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // ResponseOrError holds either the response to a request or an error
+ // message.
+ template <typename T>
+ struct ResponseOrError {
+ using Request = T;
+ ResponseOrError();
+ ResponseOrError(const T& response);
+ ResponseOrError(T&& response);
+ ResponseOrError(const Rsp_Error& error);
+ ResponseOrError(Rsp_Error&& error);
+ ResponseOrError(const ResponseOrError& other);
+ ResponseOrError(ResponseOrError&& other) noexcept;
+
+ ResponseOrError& operator=(const ResponseOrError& other);
+ ResponseOrError& operator=(ResponseOrError&& other) noexcept;
+ bool IsError() const { return is_error; }
+ std::string ToJson()
+ {
+ if (is_error) return error.ToJson();
+ return response.ToJson();
+ }
+ T response;
+ Rsp_Error error; // empty represents success.
+ bool is_error;
+ };
+
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(): is_error(false)
+ {
+ }
+
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp), is_error(false) {}
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)), is_error(false) {}
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(const Rsp_Error& err) : error(err), is_error(true) {}
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(Rsp_Error&& err) : error(std::move(err)), is_error(true) {}
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(const ResponseOrError& other)
+ : response(other.response), error(other.error), is_error(other.is_error) {}
+ template <typename T>
+ ResponseOrError<T>::ResponseOrError(ResponseOrError&& other) noexcept
+ : response(std::move(other.response)), error(std::move(other.error)), is_error(other.is_error) {}
+ template <typename T>
+ ResponseOrError<T>& ResponseOrError<T>::operator=(
+ const ResponseOrError& other) {
+ response = other.response;
+ error = other.error;
+ is_error = other.is_error;
+ return *this;
+ }
+ template <typename T>
+ ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) noexcept
+ {
+ response = std::move(other.response);
+ error = std::move(other.error);
+ is_error = other.is_error;
+ return *this;
+ }
+
+}
+
+
+class RemoteEndPoint :MessageIssueHandler
+{
+
+ template <typename F, int N>
+ using ParamType = lsp::traits::ParameterType<F, N>;
+
+ template <typename T>
+ using IsRequest = lsp::traits::EnableIfIsType<RequestInMessage, T>;
+
+ template <typename T>
+ using IsResponse = lsp::traits::EnableIfIsType<ResponseInMessage, T>;
+
+ template <typename T>
+ using IsNotify = lsp::traits::EnableIfIsType<NotificationInMessage, T>;
+
+
+ template <typename F, typename ReturnType>
+ using IsRequestHandler = lsp::traits::EnableIf<lsp::traits::CompatibleWith<
+ F,
+ std::function<ReturnType(const RequestInMessage&)>>::
+ value>;
+
+ template <typename F, typename ReturnType>
+ using IsRequestHandlerWithMonitor = lsp::traits::EnableIf<lsp::traits::CompatibleWith<
+ F,
+ std::function<ReturnType(const RequestInMessage&,const CancelMonitor&)>>::
+ value>;
+
+public:
+
+
+ RemoteEndPoint(const std::shared_ptr <MessageJsonHandler>& json_handler,
+ const std::shared_ptr < Endpoint >& localEndPoint,
+ lsp::Log& _log, uint8_t max_workers = 2);
+
+ ~RemoteEndPoint() override;
+ template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response>
+ IsRequestHandler< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler)
+ {
+ ProcessRequestJsonHandler(handler);
+ local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) {
+ auto req = reinterpret_cast<const RequestType*>(msg.get());
+ lsp::ResponseOrError<ResponseType> res(handler(*req));
+ if (res.is_error) {
+ res.error.id = req->id;
+ send(res.error);
+ }
+ else
+ {
+ res.response.id = req->id;
+ send(res.response);
+ }
+ return true;
+ });
+ }
+ template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response>
+ IsRequestHandlerWithMonitor< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) {
+ ProcessRequestJsonHandler(handler);
+ local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) {
+ auto req = static_cast<const RequestType*>(msg.get());
+ lsp::ResponseOrError<ResponseType> res(handler(*req , getCancelMonitor(req->id)));
+ if (res.is_error) {
+ res.error.id = req->id;
+ send(res.error);
+ }
+ else
+ {
+ res.response.id = req->id;
+ send(res.response);
+ }
+ return true;
+ });
+ }
+ using RequestErrorCallback = std::function<void(const Rsp_Error&)>;
+
+ template <typename T, typename F, typename ResponseType = ParamType<F, 0> >
+ void send(T& request, F&& handler, RequestErrorCallback onError)
+ {
+ ProcessRequestJsonHandler(handler);
+ auto cb = [=](std::unique_ptr<LspMessage> msg) {
+ if (!msg)
+ return true;
+ const auto result = msg.get();
+
+ if (static_cast<ResponseInMessage*>(result)->IsErrorType()) {
+ const auto rsp_error = static_cast<const Rsp_Error*>(result);
+ onError(*rsp_error);
+ }
+ else {
+ handler(*static_cast<ResponseType*>(result));
+ }
+
+ return true;
+ };
+ internalSendRequest(request, cb);
+ }
+
+
+ template <typename F, typename NotifyType = ParamType<F, 0> >
+ IsNotify<NotifyType> registerHandler(F&& handler) {
+ {
+ std::lock_guard<std::mutex> lock(m_sendMutex);
+ if (!jsonHandler->GetNotificationJsonHandler(NotifyType::kMethodInfo))
+ {
+ jsonHandler->SetNotificationJsonHandler(NotifyType::kMethodInfo,
+ [](Reader& visitor)
+ {
+ return NotifyType::ReflectReader(visitor);
+ });
+ }
+ }
+ local_endpoint->registerNotifyHandler(NotifyType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) {
+ handler(*static_cast<NotifyType*>(msg.get()));
+ return true;
+ });
+ }
+
+ template <typename T, typename = IsRequest<T>>
+ std::future< lsp::ResponseOrError<typename T::Response> > send(T& request) {
+
+ ProcessResponseJsonHandler(request);
+ using Response = typename T::Response;
+ auto promise = std::make_shared< std::promise<lsp::ResponseOrError<Response>>>();
+ auto cb = [=](std::unique_ptr<LspMessage> msg) {
+ if (!msg)
+ return true;
+ auto result = msg.get();
+
+ if (reinterpret_cast<ResponseInMessage*>(result)->IsErrorType())
+ {
+ Rsp_Error* rsp_error = static_cast<Rsp_Error*>(result);
+ Rsp_Error temp;
+ std::swap(temp, *rsp_error);
+ promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp))));
+ }
+ else
+ {
+ Response temp;
+ std::swap(temp, *static_cast<Response*>(result));
+ promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp))));
+ }
+ return true;
+ };
+ internalSendRequest(request, cb);
+ return promise->get_future();
+ }
+
+ template <typename T, typename = IsRequest<T>>
+ std::unique_ptr<lsp::ResponseOrError<typename T::Response>> waitResponse(T& request, const unsigned time_out = 0)
+ {
+ auto future_rsp = send(request);
+ if (time_out == 0)
+ {
+ future_rsp.wait();
+ }
+ else
+ {
+ auto state = future_rsp.wait_for(std::chrono::milliseconds(time_out));
+ if (std::future_status::timeout == state)
+ {
+ return {};
+ }
+ }
+
+ using Response = typename T::Response;
+ return std::make_unique<lsp::ResponseOrError<Response>>(std::move(future_rsp.get()));
+ }
+
+ void send(NotificationInMessage& msg)
+ {
+ sendMsg(msg);
+ }
+
+ void send(ResponseInMessage& msg)
+ {
+ sendMsg(msg);
+ }
+
+ void sendNotification(NotificationInMessage& msg)
+ {
+ send(msg);
+ }
+ void sendResponse(ResponseInMessage& msg)
+ {
+ send(msg);
+ }
+ void startProcessingMessages(std::shared_ptr<lsp::istream> r,
+ std::shared_ptr<lsp::ostream> w);
+
+ bool IsWorking() const
+ {
+ if (message_producer_thread_)
+ return true;
+ return false;
+ }
+ void Stop();
+
+ std::unique_ptr<LspMessage> internalWaitResponse(RequestInMessage&, unsigned time_out = 0);
+
+ void internalSendRequest(RequestInMessage&, GenericResponseHandler);
+
+ void handle(std::vector<MessageIssue>&&) override;
+ void handle(MessageIssue&&) override;
+private:
+ CancelMonitor getCancelMonitor(const lsRequestId&);
+ void sendMsg(LspMessage& msg);
+ void mainLoop(std::unique_ptr<LspMessage>);
+ bool dispatch(const std::string&);
+ template <typename F, typename RequestType = ParamType<F, 0>>
+ IsRequest<RequestType> ProcessRequestJsonHandler(const F& handler) {
+ std::lock_guard<std::mutex> lock(m_sendMutex);
+ if (!jsonHandler->GetRequestJsonHandler(RequestType::kMethodInfo))
+ {
+ jsonHandler->SetRequestJsonHandler(RequestType::kMethodInfo,
+ [](Reader& visitor)
+ {
+ return RequestType::ReflectReader(visitor);
+ });
+ }
+ }
+ template <typename T, typename = IsRequest<T>>
+ void ProcessResponseJsonHandler(T& request)
+ {
+ using Response = typename T::Response;
+ std::lock_guard<std::mutex> lock(m_sendMutex);
+ if (!jsonHandler->GetResponseJsonHandler(T::kMethodInfo))
+ {
+ jsonHandler->SetResponseJsonHandler(T::kMethodInfo, [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return Response::ReflectReader(visitor);
+ });
+ }
+ }
+
+ struct Data;
+
+ Data* d_ptr;
+
+ std::shared_ptr < MessageJsonHandler> jsonHandler;
+ std::mutex m_sendMutex;
+
+ std::shared_ptr < Endpoint > local_endpoint;
+public:
+ std::shared_ptr < std::thread > message_producer_thread_;
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RequestInMessage.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RequestInMessage.h
new file mode 100644
index 0000000000..163d038a2e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/RequestInMessage.h
@@ -0,0 +1,70 @@
+#pragma once
+
+
+#include "serializer.h"
+#include <atomic>
+#include <mutex>
+#include "lsRequestId.h"
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/method_type.h"
+#include "lsResponseMessage.h"
+
+struct RequestInMessage : public LspMessage {
+ // number or string, actually no null
+ lsRequestId id;
+ std::string method;
+ Kind GetKid() override
+ {
+ return REQUEST_MESSAGE;
+ }
+
+};
+
+
+
+template <class T, class TDerived >
+struct lsRequest : public RequestInMessage
+{
+ lsRequest(MethodType _method)
+ {
+ method = _method;
+ }
+ MethodType GetMethodType() const override { return method.c_str(); }
+ void SetMethodType(MethodType _method) override
+ {
+ method = _method;
+ } \
+ void ReflectWriter(Writer& writer) override {
+ Reflect(writer, static_cast<TDerived&>(*this));
+ }
+
+ static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) {
+
+ TDerived* temp = new TDerived();
+ std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp);
+ // Reflect may throw and *message will be partially deserialized.
+ Reflect(visitor, static_cast<TDerived&>(*temp));
+ return message;
+ }
+ void swap(lsRequest& arg) noexcept
+ {
+ id.swap(arg.id);
+ method.swap(method);
+ std::swap(params, arg.params);
+ }
+ T params;
+};
+
+
+#define DEFINE_REQUEST_RESPONSE_TYPE(MSG,request_param,response_result,methodInfo)\
+namespace MSG {\
+ struct response :public ResponseMessage< response_result, response> {}; \
+ struct request : public lsRequest< request_param , request >{\
+ static constexpr MethodType kMethodInfo = methodInfo;\
+ request():lsRequest(kMethodInfo){} \
+ using Response = response;\
+ };\
+};\
+MAKE_REFLECT_STRUCT(MSG::request, jsonrpc, id, method, params);\
+MAKE_REFLECT_STRUCT(MSG::response, jsonrpc, id, result);
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/ScopeExit.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/ScopeExit.h
new file mode 100644
index 0000000000..024b700b4a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/ScopeExit.h
@@ -0,0 +1,59 @@
+//===- llvm/ADT/ScopeExit.h - Execute code at scope exit --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the make_scope_exit function, which executes user-defined
+// cleanup logic at scope exit.
+//
+//===----------------------------------------------------------------------===//
+#pragma once
+#include <type_traits>
+#include <utility>
+
+namespace lsp {
+namespace detail {
+
+template <typename Callable> class scope_exit {
+ Callable ExitFunction;
+ bool Engaged = true; // False once moved-from or release()d.
+
+public:
+ template <typename Fp>
+ explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {}
+
+ scope_exit(scope_exit &&Rhs)
+ : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) {
+ Rhs.release();
+ }
+ scope_exit(const scope_exit &) = delete;
+ scope_exit &operator=(scope_exit &&) = delete;
+ scope_exit &operator=(const scope_exit &) = delete;
+
+ void release() { Engaged = false; }
+
+ ~scope_exit() {
+ if (Engaged)
+ ExitFunction();
+ }
+};
+
+} // end namespace detail
+
+// Keeps the callable object that is passed in, and execute it at the
+// destruction of the returned object (usually at the scope exit where the
+// returned object is kept).
+//
+// Interface is specified by p0052r2.
+template <typename Callable>
+ detail::scope_exit<typename std::decay<Callable>::type>
+make_scope_exit(Callable &&F) {
+ return detail::scope_exit<typename std::decay<Callable>::type>(
+ std::forward<Callable>(F));
+}
+
+} // end namespace lsp
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.cpp
new file mode 100644
index 0000000000..c9df407980
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.cpp
@@ -0,0 +1,191 @@
+
+#include "StreamMessageProducer.h"
+#include <cassert>
+
+#include "stream.h"
+
+
+bool StartsWith(std::string value, std::string start);
+bool StartsWith(std::string value, std::string start) {
+ if (start.size() > value.size())
+ return false;
+ return std::equal(start.begin(), start.end(), value.begin());
+}
+
+using namespace std;
+namespace
+{
+ string JSONRPC_VERSION = "2.0";
+ string CONTENT_LENGTH_HEADER = "Content-Length";
+ string CONTENT_TYPE_HEADER = "Content-Type";
+ string JSON_MIME_TYPE = "application/json";
+ string CRLF = "\r\n";
+
+}
+
+ void StreamMessageProducer::parseHeader(std::string& line, StreamMessageProducer::Headers& headers)
+ {
+ int sepIndex = line.find(':');
+ if (sepIndex >= 0) {
+ auto key = line.substr(0, sepIndex);
+ if(key == CONTENT_LENGTH_HEADER)
+ {
+ headers.contentLength = atoi(line.substr(sepIndex + 1).data());
+ }
+ else if(key == CONTENT_TYPE_HEADER)
+ {
+ int charsetIndex = line.find("charset=");
+ if (charsetIndex >= 0)
+ headers.charset = line.substr(charsetIndex + 8);
+ }
+ }
+ }
+
+
+void StreamMessageProducer::listen(MessageConsumer callBack)
+{
+ if(!input)
+ return;
+
+ keepRunning = true;
+ bool newLine = false;
+ Headers headers;
+ string headerBuilder ;
+ string debugBuilder ;
+ // Read the content length. It is terminated by the "\r\n" sequence.
+ while (keepRunning)
+ {
+ if(input->bad())
+ {
+ std::string info = "Input stream is bad.";
+ auto what = input->what();
+ if (what.size())
+ {
+ info += "Reason:";
+ info += input->what();
+ }
+ MessageIssue issue(info, lsp::Log::Level::SEVERE);
+ issueHandler.handle(std::move(issue));
+ return;
+ }
+ if(input->fail())
+ {
+ std::string info = "Input fail.";
+ auto what = input->what();
+ if(what.size())
+ {
+ info += "Reason:";
+ info += input->what();
+ }
+ MessageIssue issue(info, lsp::Log::Level::WARNING);
+ issueHandler.handle(std::move(issue));
+ if(input->need_to_clear_the_state())
+ input->clear();
+ else
+ {
+ return;
+ }
+ }
+ int c = input->get();
+ if (c == EOF) {
+ // End of input stream has been reached
+ keepRunning = false;
+ }
+ else
+ {
+
+ debugBuilder.push_back((char)c);
+ if (c == '\n')
+ {
+ if (newLine) {
+ // Two consecutive newlines have been read, which signals the start of the message content
+ if (headers.contentLength <= 0)
+ {
+ string info = "Unexpected token:" + debugBuilder;
+ info = +" (expected Content-Length: sequence);";
+ MessageIssue issue(info, lsp::Log::Level::WARNING);
+ issueHandler.handle(std::move(issue));
+ }
+ else {
+ bool result = handleMessage(headers,callBack);
+ if (!result)
+ keepRunning = false;
+ newLine = false;
+ }
+ headers.clear();
+ debugBuilder.clear();
+ }
+ else if (!headerBuilder.empty()) {
+ // A single newline ends a header line
+ parseHeader(headerBuilder, headers);
+ headerBuilder.clear();
+ }
+ newLine = true;
+ }
+ else if (c != '\r') {
+ // Add the input to the current header line
+
+ headerBuilder.push_back((char)c);
+ newLine = false;
+ }
+ }
+ }
+
+}
+
+void StreamMessageProducer::bind(std::shared_ptr<lsp::istream>_in)
+{
+ input = _in;
+}
+
+bool StreamMessageProducer::handleMessage(Headers& headers ,MessageConsumer callBack)
+{
+ // Read content.
+ auto content_length = headers.contentLength;
+ std::string content(content_length,0);
+ auto data = &content[0];
+ input->read(data, content_length);
+ if (input->bad())
+ {
+ std::string info = "Input stream is bad.";
+ auto what = input->what();
+ if (!what.empty())
+ {
+ info += "Reason:";
+ info += input->what();
+ }
+ MessageIssue issue(info, lsp::Log::Level::SEVERE);
+ issueHandler.handle(std::move(issue));
+ return false;
+ }
+
+ if (input->eof())
+ {
+ MessageIssue issue("No more input when reading content body", lsp::Log::Level::INFO);
+ issueHandler.handle(std::move(issue));
+ return false;
+ }
+ if (input->fail())
+ {
+ std::string info = "Input fail.";
+ auto what = input->what();
+ if (!what.empty())
+ {
+ info += "Reason:";
+ info += input->what();
+ }
+ MessageIssue issue(info, lsp::Log::Level::WARNING);
+ issueHandler.handle(std::move(issue));
+ if (input->need_to_clear_the_state())
+ input->clear();
+ else
+ {
+ return false;
+ }
+ }
+
+ callBack(std::move(content));
+
+ return true;
+}
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.h
new file mode 100644
index 0000000000..439a9f1b0e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/StreamMessageProducer.h
@@ -0,0 +1,48 @@
+#pragma once
+#include <string>
+#include <functional>
+#include "MessageProducer.h"
+#include <iostream>
+#include <memory>
+#include "MessageIssue.h"
+
+namespace lsp {
+ class istream;
+}
+
+class StreamMessageProducer : public MessageProducer
+{
+public:
+ struct Headers
+ {
+ int contentLength = -1;
+ std::string charset;
+ void clear()
+ {
+ contentLength = -1;
+ charset.clear();
+ }
+ };
+ bool handleMessage(Headers& headers, MessageConsumer callBack);
+ StreamMessageProducer(
+ MessageIssueHandler& message_issue_handler, std::shared_ptr < lsp::istream> _input)
+ : issueHandler(message_issue_handler),
+ input(_input)
+ {
+ }
+ StreamMessageProducer(
+ MessageIssueHandler& message_issue_handler)
+ : issueHandler(message_issue_handler)
+ {
+ }
+
+ bool keepRunning = false;
+ void listen(MessageConsumer) override;
+ void bind(std::shared_ptr < lsp::istream>);
+ void parseHeader(std::string& line, Headers& headers);
+private:
+ MessageIssueHandler& issueHandler;
+ std::shared_ptr < lsp::istream> input;
+
+
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.cpp
new file mode 100644
index 0000000000..9188356473
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.cpp
@@ -0,0 +1,299 @@
+//
+// server.cpp
+
+#include "TcpServer.h"
+#include <signal.h>
+#include <utility>
+#include <boost/bind/bind.hpp>
+
+#include "MessageIssue.h"
+#include "stream.h"
+
+
+namespace lsp {
+ struct tcp_connect_session;
+
+
+ class tcp_stream_wrapper :public istream, public ostream
+ {
+ public:
+ tcp_stream_wrapper(tcp_connect_session& _w);
+
+ tcp_connect_session& session;
+ std::atomic<bool> quit{};
+ std::shared_ptr < MultiQueueWaiter> request_waiter;
+ ThreadedQueue< char > on_request;
+ std::string error_message;
+
+
+ bool fail() override
+ {
+ return bad();
+ }
+
+
+
+ bool eof() override
+ {
+ return bad();
+ }
+ bool good() override
+ {
+ return !bad();
+ }
+ tcp_stream_wrapper& read(char* str, std::streamsize count)
+ override
+ {
+ auto some = on_request.TryDequeueSome(static_cast<size_t>( count ));
+ for (size_t i = 0; i < some.size(); ++i)
+ {
+ str[i] = some[i];
+ }
+ for (std::streamsize i = 0; i < count; ++i)
+ {
+ str[i] = static_cast<char>(get());
+ }
+
+ return *this;
+ }
+ int get() override
+ {
+ return on_request.Dequeue();
+ }
+
+ bool bad() override;
+
+ tcp_stream_wrapper& write(const std::string& c) override;
+
+ tcp_stream_wrapper& write(std::streamsize _s) override;
+
+ tcp_stream_wrapper& flush() override
+ {
+ return *this;
+ }
+ void reset_state()
+ {
+ return;
+ }
+
+ void clear() override
+ {
+
+ }
+
+ std::string what() override;
+ bool need_to_clear_the_state() override
+ {
+ return false;
+ }
+ };
+ struct tcp_connect_session:std::enable_shared_from_this<tcp_connect_session>
+ {
+ /// Buffer for incoming data.
+ std::array<unsigned char, 8192> buffer_;
+ boost::asio::ip::tcp::socket socket_;
+ /// Strand to ensure the connection's handlers are not called concurrently.
+ boost::asio::io_context::strand strand_;
+ std::shared_ptr<tcp_stream_wrapper> proxy_;
+ explicit tcp_connect_session(boost::asio::io_context& io_context, boost::asio::ip::tcp::socket&& _socket)
+ : socket_(std::move(_socket)), strand_(io_context), proxy_(new tcp_stream_wrapper(*this))
+ {
+ do_read();
+ }
+ void do_write(const std::string& data)
+ {
+ socket_.async_write_some(boost::asio::buffer(data.data(), data.size()),
+ boost::asio::bind_executor(strand_,[this](boost::system::error_code ec, std::size_t n)
+ {
+ if (!ec)
+ {
+ return;
+ }
+ proxy_->error_message = ec.message();
+
+ }));
+ }
+ void do_read()
+ {
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::asio::bind_executor(strand_,
+ [this](boost::system::error_code ec, size_t bytes_transferred)
+ {
+ if (!ec)
+ {
+ std::vector<char> elements(buffer_.data(), buffer_.data() + bytes_transferred);
+ proxy_->on_request.EnqueueAll(std::move(elements), false);
+ do_read();
+ return;
+ }
+ proxy_->error_message = ec.message();
+
+ }));
+ }
+ };
+
+ tcp_stream_wrapper::tcp_stream_wrapper(tcp_connect_session& _w): session(_w)
+ {
+ }
+
+ bool tcp_stream_wrapper::bad()
+ {
+ return !session.socket_.is_open();
+ }
+
+ tcp_stream_wrapper& tcp_stream_wrapper::write(const std::string& c)
+ {
+ session.do_write(c);
+ return *this;
+ }
+
+ tcp_stream_wrapper& tcp_stream_wrapper::write(std::streamsize _s)
+ {
+ session.do_write(std::to_string(_s));
+ return *this;
+ }
+
+ std::string tcp_stream_wrapper::what()
+ {
+ if (error_message.size())
+ return error_message;
+
+ if(! session.socket_.is_open())
+ {
+ return "Socket is not open.";
+ }
+ return {};
+ }
+
+ struct TcpServer::Data
+ {
+ Data(
+ lsp::Log& log, uint32_t _max_workers) :
+ acceptor_(io_context_), _log(log)
+ {
+ }
+
+ ~Data()
+ {
+
+ }
+ /// The io_context used to perform asynchronous operations.
+ boost::asio::io_context io_context_;
+
+ std::shared_ptr<boost::asio::io_service::work> work;
+
+ std::shared_ptr<tcp_connect_session> _connect_session;
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+ lsp::Log& _log;
+
+ };
+
+ TcpServer::~TcpServer()
+ {
+ delete d_ptr;
+ }
+
+ TcpServer::TcpServer(const std::string& address, const std::string& port,
+ std::shared_ptr < MessageJsonHandler> json_handler,
+ std::shared_ptr < Endpoint> localEndPoint, lsp::Log& log, uint32_t _max_workers)
+ : point(json_handler, localEndPoint, log, _max_workers),d_ptr(new Data( log, _max_workers))
+
+ {
+
+ d_ptr->work = std::make_shared<boost::asio::io_service::work>(d_ptr->io_context_);
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+ boost::asio::ip::tcp::resolver resolver(d_ptr->io_context_);
+ boost::asio::ip::tcp::endpoint endpoint =
+ *resolver.resolve(address, port).begin();
+ d_ptr->acceptor_.open(endpoint.protocol());
+ d_ptr->acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ try
+ {
+ d_ptr->acceptor_.bind(endpoint);
+ }
+ catch (boost::system::system_error & e)
+ {
+ std::string temp = "Socket Server bind failed.";
+ d_ptr->_log.log(lsp::Log::Level::INFO , temp + e.what());
+ return;
+ }
+ d_ptr->acceptor_.listen();
+
+ do_accept();
+ std::string desc = "Socket TcpServer " + address + " " + port + " start.";
+ d_ptr->_log.log(lsp::Log::Level::INFO, desc);
+ }
+
+ void TcpServer::run()
+ {
+ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the TcpServer is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+ d_ptr->io_context_.run();
+
+ }
+
+ void TcpServer::stop()
+ {
+ try
+ {
+ if(d_ptr->work)
+ d_ptr->work.reset();
+
+ do_stop();
+ }
+ catch (...)
+ {
+ }
+ }
+
+ void TcpServer::do_accept()
+ {
+ d_ptr->acceptor_.async_accept(
+ [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket)
+ {
+ // Check whether the TcpServer was stopped by a signal before this
+ // completion handler had a chance to run.
+ if (!d_ptr->acceptor_.is_open())
+ {
+ return;
+ }
+
+ if (!ec)
+ {
+ if(d_ptr->_connect_session)
+ {
+ if(d_ptr->_connect_session->socket_.is_open())
+ {
+ std::string desc = "Disconnect previous client " + d_ptr->_connect_session->socket_.local_endpoint().address().to_string();
+ d_ptr->_log.log(lsp::Log::Level::INFO, desc);
+ d_ptr->_connect_session->socket_.close();
+ }
+
+ point.Stop();
+ }
+ auto local_point = socket.local_endpoint();
+
+ std::string desc = ("New client " + local_point.address().to_string() + " connect.");
+ d_ptr->_log.log(lsp::Log::Level::INFO, desc);
+ d_ptr->_connect_session = std::make_shared<tcp_connect_session>(d_ptr->io_context_,std::move(socket));
+
+ point.startProcessingMessages(d_ptr->_connect_session->proxy_, d_ptr->_connect_session->proxy_);
+ do_accept();
+ }
+ });
+ }
+
+ void TcpServer::do_stop()
+ {
+ d_ptr->acceptor_.close();
+
+ point.Stop();
+
+ }
+
+ } // namespace
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.h
new file mode 100644
index 0000000000..e533acf056
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/TcpServer.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <boost/asio.hpp>
+#include <string>
+#include "RemoteEndPoint.h"
+
+namespace lsp {
+ class Log;
+}
+namespace lsp
+{
+ /// The top-level class of the HTTP server.
+ class TcpServer
+ {
+ public:
+ TcpServer(const TcpServer&) = delete;
+ TcpServer& operator=(const TcpServer&) = delete;
+ ~TcpServer();
+ /// Construct the server to listen on the specified TCP address and port, and
+ /// serve up files from the given directory.
+ explicit TcpServer(const std::string& address, const std::string& port,
+ std::shared_ptr < MessageJsonHandler> json_handler,
+ std::shared_ptr < Endpoint> localEndPoint, lsp::Log& ,uint32_t _max_workers = 2);
+
+ /// Run the server's io_context loop.
+ void run();
+ void stop();
+
+ RemoteEndPoint point;
+ private:
+ struct Data;
+ /// Perform an asynchronous accept operation.
+ void do_accept();
+
+ /// Wait for a request to stop the server.
+ void do_stop();
+ Data* d_ptr = nullptr;
+ };
+} // namespace
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.cpp
new file mode 100644
index 0000000000..2cb83099c3
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.cpp
@@ -0,0 +1,341 @@
+#include "MessageIssue.h"
+#include "WebSocketServer.h"
+#include <iostream>
+#include <signal.h>
+#include <utility>
+#include "stream.h"
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/dispatch.hpp>
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+namespace lsp {
+
+ // Echoes back all received WebSocket messages
+ class server_session : public std::enable_shared_from_this<server_session>
+ {
+ websocket::stream<beast::tcp_stream> ws_;
+
+ beast::flat_buffer buffer_;
+ std::string user_agent_;
+ public:
+ std::shared_ptr<websocket_stream_wrapper> proxy_;
+ // Take ownership of the socket
+ explicit
+ server_session(tcp::socket&& socket,const std::string& user_agent)
+ : ws_(std::move(socket)),user_agent_(user_agent)
+ {
+ proxy_ = std::make_shared<websocket_stream_wrapper>(ws_);
+ }
+
+ // Get on the correct executor
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this server_session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(ws_.get_executor(),
+ beast::bind_front_handler(
+ &server_session::on_run,
+ shared_from_this()));
+ }
+
+ // Start the asynchronous operation
+ void
+ on_run()
+ {
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [=](websocket::response_type& res)
+ {
+ res.set(http::field::server, user_agent_.c_str());
+ }));
+ // Accept the websocket handshake
+ ws_.async_accept(
+ beast::bind_front_handler(
+ &server_session::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec)
+ {
+ if (ec)
+ return ;
+
+ // Read a message
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &server_session::on_read,
+ shared_from_this()));
+ }
+
+
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+
+ if(!ec)
+ {
+ char* data = reinterpret_cast<char*>(buffer_.data().data());
+ std::vector<char> elements(data, data + bytes_transferred);
+
+ buffer_.clear();
+ proxy_->on_request.EnqueueAll(std::move(elements), false);
+
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &server_session::on_read,
+ shared_from_this()));
+ return;
+ }
+ if (ec){
+ proxy_->error_message = ec.message();
+ }
+ }
+
+
+
+ void close()
+ {
+ if(ws_.is_open())
+ {
+ boost::system::error_code ec;
+ ws_.close(websocket::close_code::normal, ec);
+ }
+
+ }
+ };
+
+ //------------------------------------------------------------------------------
+
+ struct WebSocketServer::Data
+ {
+ Data(const std::string& user_agent, lsp::Log& log) :
+ acceptor_(io_context_), user_agent_(user_agent), _log(log)
+
+ {
+ }
+
+ ~Data()
+ {
+
+ }
+ /// The io_context used to perform asynchronous operations.
+ boost::asio::io_context io_context_;
+
+ std::shared_ptr<boost::asio::io_service::work> work;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+ std::shared_ptr < server_session> _server_session;
+
+ std::string user_agent_;
+ lsp::Log& _log;
+
+ };
+
+ websocket_stream_wrapper::websocket_stream_wrapper(boost::beast::websocket::stream<boost::beast::tcp_stream>& _w):
+ ws_(_w), request_waiter(new MultiQueueWaiter()),
+ on_request(request_waiter)
+ {
+ }
+
+ bool websocket_stream_wrapper::fail()
+ {
+ return bad();
+ }
+
+ bool websocket_stream_wrapper::eof()
+ {
+ return bad();
+ }
+
+ bool websocket_stream_wrapper::good()
+ {
+ return !bad();
+ }
+
+ websocket_stream_wrapper& websocket_stream_wrapper::read(char* str, std::streamsize count)
+ {
+ auto some = on_request.TryDequeueSome(static_cast<size_t>(count));
+
+ for (size_t i = 0; i < some.size(); ++i)
+ {
+ str[i] = some[i];
+ }
+ for (std::streamsize i = 0; i < count; ++i)
+ {
+ str[i] = static_cast<char>(get());
+ }
+ return *this;
+ }
+
+ int websocket_stream_wrapper::get()
+ {
+ return on_request.Dequeue();
+ }
+
+ bool websocket_stream_wrapper::bad()
+ {
+ return !ws_.next_layer().socket().is_open();
+ }
+
+ websocket_stream_wrapper& websocket_stream_wrapper::write(const std::string& c)
+ {
+ ws_.write(boost::asio::buffer(std::string(c)));
+ return *this;
+ }
+
+
+ websocket_stream_wrapper& websocket_stream_wrapper::write(std::streamsize _s)
+ {
+ std::ostringstream temp;
+ temp << _s;
+ ws_.write(boost::asio::buffer(temp.str()));
+ return *this;
+ }
+
+ websocket_stream_wrapper& websocket_stream_wrapper::flush()
+ {
+ return *this;
+ }
+
+ void websocket_stream_wrapper::clear()
+ {
+ }
+
+ std::string websocket_stream_wrapper::what()
+ {
+ if (!error_message.empty())
+ return error_message;
+
+ if (!ws_.next_layer().socket().is_open())
+ {
+ return "Socket is not open.";
+ }
+ return {};
+ }
+
+ WebSocketServer::~WebSocketServer()
+ {
+ delete d_ptr;
+ }
+
+ WebSocketServer::WebSocketServer(const std::string& user_agent, const std::string& address, const std::string& port,
+ std::shared_ptr < MessageJsonHandler> json_handler,
+ std::shared_ptr < Endpoint> localEndPoint, lsp::Log& log, uint32_t _max_workers)
+ : point(json_handler,localEndPoint,log, _max_workers),d_ptr(new Data(user_agent,log))
+
+ {
+
+ d_ptr->work = std::make_shared<boost::asio::io_service::work>(d_ptr->io_context_);
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+ boost::asio::ip::tcp::resolver resolver(d_ptr->io_context_);
+ boost::asio::ip::tcp::endpoint endpoint =
+ *resolver.resolve(address, port).begin();
+ d_ptr->acceptor_.open(endpoint.protocol());
+ d_ptr->acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ try
+ {
+ d_ptr->acceptor_.bind(endpoint);
+ }
+ catch (boost::system::system_error & e)
+ {
+ std::string temp = "Socket Server blid faild.";
+ d_ptr->_log.log(lsp::Log::Level::INFO , temp + e.what());
+ return;
+ }
+ d_ptr->acceptor_.listen();
+
+ do_accept();
+ std::string desc = "Socket WebSocketServer " + address + " " + port + " start.";
+ d_ptr->_log.log(lsp::Log::Level::INFO, desc);
+ }
+
+ void WebSocketServer::run()
+ {
+ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the WebSocketServer is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+ d_ptr->io_context_.run();
+
+ }
+
+ void WebSocketServer::stop()
+ {
+ try
+ {
+ if(d_ptr->work)
+ d_ptr->work.reset();
+
+ do_stop();
+ }
+ catch (...)
+ {
+ }
+ }
+
+ void WebSocketServer::do_accept()
+ {
+ d_ptr->acceptor_.async_accept(
+ [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket)
+ {
+ // Check whether the WebSocketServer was stopped by a signal before this
+ // completion handler had a chance to run.
+ if (!d_ptr->acceptor_.is_open())
+ {
+ return;
+ }
+ if (!ec)
+ {
+ if(d_ptr->_server_session)
+ {
+ try
+ {
+ d_ptr->_server_session->close();
+ point.Stop();
+ }
+ catch (...)
+ {
+ }
+ }
+ d_ptr->_server_session = std::make_shared<server_session>(std::move(socket), d_ptr->user_agent_);
+ d_ptr->_server_session->run();
+
+ point.startProcessingMessages(d_ptr->_server_session->proxy_, d_ptr->_server_session->proxy_);
+ do_accept();
+ }
+
+ });
+ }
+
+ void WebSocketServer::do_stop()
+ {
+ d_ptr->acceptor_.close();
+
+ point.Stop();
+
+ }
+
+ } // namespace
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.h
new file mode 100644
index 0000000000..5206525ceb
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/WebSocketServer.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <boost/asio.hpp>
+#include <string>
+#include <boost/beast/core/tcp_stream.hpp>
+#include <boost/beast/websocket/stream.hpp>
+
+
+#include "RemoteEndPoint.h"
+#include "stream.h"
+#include "threaded_queue.h"
+
+namespace lsp {
+ class Log;
+}
+
+
+namespace lsp
+{
+
+
+
+ class websocket_stream_wrapper :public istream, public ostream
+ {
+ public:
+
+ websocket_stream_wrapper(boost::beast::websocket::stream<boost::beast::tcp_stream>& _w);
+
+ boost::beast::websocket::stream<boost::beast::tcp_stream>& ws_;
+ std::atomic<bool> quit{};
+ std::shared_ptr < MultiQueueWaiter> request_waiter;
+ ThreadedQueue< char > on_request;
+ std::string error_message;
+ bool fail() override;
+
+ bool eof() override;
+
+ bool good() override;
+
+ websocket_stream_wrapper& read(char* str, std::streamsize count) override;
+
+ int get() override;
+
+ bool bad() override;
+
+ websocket_stream_wrapper& write(const std::string& c) override;
+
+ websocket_stream_wrapper& write(std::streamsize _s) override;
+
+ websocket_stream_wrapper& flush() override;
+
+ void clear() override;
+
+ std::string what() override;
+ };
+
+ /// The top-level class of the HTTP server.
+ class WebSocketServer
+ {
+ public:
+ WebSocketServer(const WebSocketServer&) = delete;
+ WebSocketServer& operator=(const WebSocketServer&) = delete;
+ ~WebSocketServer();
+ /// Construct the server to listen on the specified TCP address and port, and
+ /// serve up files from the given directory.
+ explicit WebSocketServer(const std::string& user_agent, const std::string& address, const std::string& port,
+ std::shared_ptr < MessageJsonHandler> json_handler,
+ std::shared_ptr < Endpoint> localEndPoint, lsp::Log& ,uint32_t _max_workers = 2);
+
+ /// Run the server's io_context loop.
+ void run();
+ void stop();
+
+ RemoteEndPoint point;
+ private:
+ struct Data;
+ /// Perform an asynchronous accept operation.
+ void do_accept();
+
+ /// Wait for a request to stop the server.
+ void do_stop();
+ Data* d_ptr = nullptr;
+
+
+ };
+
+ } // namespace
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/json.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/json.h
new file mode 100644
index 0000000000..98ee91b544
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/json.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include "serializer.h"
+
+#include <rapidjson/document.h>
+#include <rapidjson/prettywriter.h>
+
+class JsonReader : public Reader {
+
+ std::vector<const char*> path_;
+
+ public:
+ rapidjson::GenericValue<rapidjson::UTF8<>>* m_;
+ JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>>* m) : m_(m) {}
+ SerializeFormat Format() const override { return SerializeFormat::Json; }
+
+ bool IsBool() override { return m_->IsBool(); }
+ bool IsNull() override { return m_->IsNull(); }
+ bool IsArray() override { return m_->IsArray(); }
+ bool IsInt() override { return m_->IsInt(); }
+ bool IsInt64() override { return m_->IsInt64(); }
+ bool IsUint64() override { return m_->IsUint64(); }
+ bool IsDouble() override { return m_->IsDouble(); }
+ bool IsNumber() override { return m_->IsNumber(); }
+ bool IsString() override { return m_->IsString(); }
+
+ void GetNull() override {}
+ bool GetBool() override { return m_->GetBool(); }
+ int GetInt() override { return m_->GetInt(); }
+ uint32_t GetUint32() override { return uint32_t(m_->GetUint64()); }
+ int64_t GetInt64() override { return m_->GetInt64(); }
+ uint64_t GetUint64() override { return m_->GetUint64(); }
+ double GetDouble() override { return m_->GetDouble(); }
+ std::string GetString() override { return m_->GetString(); }
+
+ bool HasMember(const char* x) override
+ {
+ if (m_->IsObject())
+ return m_->HasMember(x);
+ else
+ return false;
+ }
+ std::unique_ptr<Reader> operator[](const char* x) override {
+ auto& sub = (*m_)[x];
+ return std::unique_ptr<JsonReader>(new JsonReader(&sub));
+ }
+
+ std::string ToString() const override;
+
+ void IterMap(std::function<void(const char*, Reader&)> fn) override;
+
+ void IterArray(std::function<void(Reader&)> fn) override;
+
+ void DoMember(const char* name, std::function<void(Reader&)> fn) override;
+
+ std::string GetPath() const;
+};
+
+class JsonWriter : public Writer {
+
+ public:
+ rapidjson::Writer<rapidjson::StringBuffer>* m_;
+
+ JsonWriter(rapidjson::Writer<rapidjson::StringBuffer>* m) : m_(m) {}
+ SerializeFormat Format() const override { return SerializeFormat::Json; }
+
+ void Null() override { m_->Null(); }
+ void Bool(bool x) override { m_->Bool(x); }
+ void Int(int x) override { m_->Int(x); }
+ void Uint32(uint32_t x) override { m_->Uint64(x); }
+ void Int64(int64_t x) override { m_->Int64(x); }
+ void Uint64(uint64_t x) override { m_->Uint64(x); }
+ void Double(double x) override { m_->Double(x); }
+ void String(const char* x) override { m_->String(x); }
+ void String(const char* x, size_t len) override { m_->String(x, len); }
+ void StartArray(size_t) override { m_->StartArray(); }
+ void EndArray() override { m_->EndArray(); }
+ void StartObject() override { m_->StartObject(); }
+ void EndObject() override { m_->EndObject(); }
+ void Key(const char* name) override { m_->Key(name); }
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsRequestId.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsRequestId.h
new file mode 100644
index 0000000000..87e94669ab
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsRequestId.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+struct lsRequestId {
+ // The client can send the request id as an int or a string. We should output
+ // the same format we received.
+ enum Type { kNone, kInt, kString };
+ Type type = kNone;
+
+ int value = -1;
+ std::string k_string;
+ bool has_value() const { return type != kNone; }
+ void swap(lsRequestId& arg) noexcept
+ {
+ std::swap(arg, *this);
+ }
+ void set(int v)
+ {
+ value = v;
+ type = kInt;
+ }
+ void set(const std::string& v)
+ {
+ k_string = v;
+ type = kString;
+ }
+ bool operator==(const lsRequestId& rhs) const
+ {
+ if (type != rhs.type) return false;
+ if (type == kInt)
+ return value == rhs.value;
+ return k_string == rhs.k_string;
+ }
+ bool operator!=(const lsRequestId& rhs) const
+ {
+ return !operator==(rhs);
+ }
+ bool operator<(const lsRequestId& rhs) const
+ {
+ if (type != rhs.type) return false;
+ if (type == kInt)
+ return value < rhs.value;
+ return k_string < rhs.k_string;
+ }
+};
+void Reflect(Reader& visitor, lsRequestId& value);
+void Reflect(Writer& visitor, lsRequestId& value);
+
+// Debug method to convert an id to a string.
+std::string ToString(const lsRequestId& id); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsResponseMessage.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsResponseMessage.h
new file mode 100644
index 0000000000..ba94167cf8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/lsResponseMessage.h
@@ -0,0 +1,71 @@
+#pragma once
+#include "serializer.h"
+#include "lsRequestId.h"
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/method_type.h"
+
+
+struct ResponseInMessage :public LspMessage {
+
+ lsRequestId id;
+ std::string m_methodType;
+
+ virtual MethodType GetMethodType() const override
+ {
+ return m_methodType.data();
+ };
+ virtual void SetMethodType(MethodType _type) override
+ {
+ m_methodType = _type;
+ };
+
+ Kind GetKid() override
+ {
+ return RESPONCE_MESSAGE;
+ }
+ virtual bool IsErrorType()
+ {
+ return false;
+ }
+};
+template <class TDerived >
+struct BaseResponseMessage : ResponseInMessage {
+
+ void ReflectWriter(Writer& writer) override {
+ Reflect(writer, static_cast<TDerived&>(*this));
+ }
+ static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) {
+
+ TDerived* temp = new TDerived();
+ std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp);
+ // Reflect may throw and *message will be partially deserialized.
+ Reflect(visitor, static_cast<TDerived&>(*temp));
+ return message;
+ }
+
+};
+
+
+template <class T, class TDerived >
+struct ResponseMessage : BaseResponseMessage<TDerived> {
+ T result;
+ void swap(ResponseMessage<T, TDerived>& arg) noexcept
+ {
+ std::swap(result, arg.result);
+ this->id.swap(arg.id);
+ this->m_methodType.swap(arg.m_methodType);
+ }
+};
+
+template <class T, class TDerived >
+struct ResponseError : BaseResponseMessage<TDerived> {
+ T error;
+ bool IsErrorType() override { return true; }
+ void swap(ResponseError<T, TDerived>& arg) noexcept
+ {
+
+ this->id.swap(arg.id);
+ this->m_methodType.swap(arg.m_methodType);
+ std::swap(error, arg.error);
+ }
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.cpp
new file mode 100644
index 0000000000..e84455402c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.cpp
@@ -0,0 +1,88 @@
+#include "message.h"
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include "serializer.h"
+#include "lsRequestId.h"
+#include "RequestInMessage.h"
+#include "Condition.h"
+#include "json.h"
+
+void LspMessage::Write(std::ostream& out) {
+ rapidjson::StringBuffer output;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(output);
+ JsonWriter json_writer{ &writer };
+ ReflectWriter(json_writer);
+
+ const auto value = std::string("Content-Length: ") + std::to_string(output.GetSize()) + "\r\n\r\n" + output.GetString();
+ out << value;
+ out.flush();
+}
+
+std::string LspMessage::ToJson() {
+ rapidjson::StringBuffer output;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(output);
+ JsonWriter json_writer{ &writer };
+ this->ReflectWriter(json_writer);
+ return output.GetString();
+}
+
+void Reflect(Reader& visitor, lsRequestId& value) {
+ if (visitor.IsInt()) {
+ value.type = lsRequestId::kInt;
+ value.value = visitor.GetInt();
+ }
+ else if (visitor.IsInt64()) {
+ value.type = lsRequestId::kInt;
+ // `lsRequestId.value` is an `int`, so we're forced to truncate.
+ value.value = static_cast<int>(visitor.GetInt64());
+ }
+ else if (visitor.IsString()) {
+ value.type = lsRequestId::kString;
+ value.k_string = visitor.GetString();
+ value.value = atoi(value.k_string.c_str());
+
+ }
+ else {
+ value.type = lsRequestId::kNone;
+ value.value = -1;
+ }
+}
+
+void Reflect(Writer& visitor, lsRequestId& value) {
+ switch (value.type) {
+ case lsRequestId::kNone:
+ visitor.Null();
+ break;
+ case lsRequestId::kInt:
+ visitor.Int(value.value);
+ break;
+ case lsRequestId::kString:
+
+ if(value.k_string.empty())
+ {
+ std::string str = std::to_string(value.value);
+ visitor.String(str.c_str(), str.length());
+ }
+ else
+ {
+ visitor.String(value.k_string.c_str(), value.k_string.length());
+ }
+ break;
+ }
+}
+
+std::string ToString(const lsRequestId& id) {
+ if (id.type != lsRequestId::kNone)
+ {
+ if(id.type == lsRequestId::kString)
+ {
+ if (!id.k_string.empty())
+ return id.k_string;
+ }
+ return std::to_string(id.value);
+ }
+
+ return "";
+}
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.h
new file mode 100644
index 0000000000..6603f3fb3a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/message.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <atomic>
+#include <string>
+#include <iostream>
+#include <LibLsp/JsonRpc/serializer.h>
+#include "LibLsp/lsp/method_type.h"
+
+struct LspMessage
+{
+public:
+ std::string jsonrpc = "2.0";
+ virtual void ReflectWriter(Writer&) = 0;
+
+ // Send the message to the language client by writing it to stdout.
+ void Write(std::ostream& out);
+
+
+ virtual MethodType GetMethodType() const = 0;
+ virtual void SetMethodType(MethodType) = 0;
+
+ virtual ~LspMessage()=default;
+ enum Kind
+ {
+ REQUEST_MESSAGE,
+ RESPONCE_MESSAGE,
+ NOTIFICATION_MESSAGE
+ };
+
+ virtual Kind GetKid() = 0;
+ virtual std::string ToJson() ;
+
+};
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/optional.hpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/optional.hpp
new file mode 100644
index 0000000000..86e3b407c6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/optional.hpp
@@ -0,0 +1,1846 @@
+//
+// Copyright (c) 2014-2021 Martin Moene
+//
+// https://github.com/martinmoene/optional-lite
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#ifndef NONSTD_OPTIONAL_LITE_HPP
+#define NONSTD_OPTIONAL_LITE_HPP
+
+#define optional_lite_MAJOR 3
+#define optional_lite_MINOR 5
+#define optional_lite_PATCH 0
+
+#define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
+
+#define optional_STRINGIFY( x ) optional_STRINGIFY_( x )
+#define optional_STRINGIFY_( x ) #x
+
+// optional-lite configuration:
+
+#define optional_OPTIONAL_DEFAULT 0
+#define optional_OPTIONAL_NONSTD 1
+#define optional_OPTIONAL_STD 2
+
+// tweak header support:
+
+#ifdef __has_include
+# if __has_include(<nonstd/optional.tweak.hpp>)
+# include <nonstd/optional.tweak.hpp>
+# endif
+#define optional_HAVE_TWEAK_HEADER 1
+#else
+#define optional_HAVE_TWEAK_HEADER 0
+//# pragma message("optional.hpp: Note: Tweak header not supported.")
+#endif
+
+// optional selection and configuration:
+
+#if !defined( optional_CONFIG_SELECT_OPTIONAL )
+# define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
+#endif
+
+// Control presence of extensions:
+
+#ifndef optional_CONFIG_NO_EXTENSIONS
+#define optional_CONFIG_NO_EXTENSIONS 0
+#endif
+
+// Control presence of exception handling (try and auto discover):
+
+#ifndef optional_CONFIG_NO_EXCEPTIONS
+# if defined(_MSC_VER)
+# include <cstddef> // for _HAS_EXCEPTIONS
+# endif
+# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
+# define optional_CONFIG_NO_EXCEPTIONS 0
+# else
+# define optional_CONFIG_NO_EXCEPTIONS 1
+# endif
+#endif
+
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef optional_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define optional_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+#define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L )
+#define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L )
+#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
+#define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L )
+#define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L )
+#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L )
+
+// C++ language version (represent 98 as 3):
+
+#define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
+
+// Use C++17 std::optional if available and requested:
+
+#if optional_CPP17_OR_GREATER && defined(__has_include )
+# if __has_include( <optional> )
+# define optional_HAVE_STD_OPTIONAL 1
+# else
+# define optional_HAVE_STD_OPTIONAL 0
+# endif
+#else
+# define optional_HAVE_STD_OPTIONAL 0
+#endif
+
+#define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
+
+//
+// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
+//
+
+#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
+#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
+
+// C++17 std::in_place in <utility>:
+
+#if optional_CPP17_OR_GREATER
+
+#include <utility>
+
+namespace nonstd {
+
+using std::in_place;
+using std::in_place_type;
+using std::in_place_index;
+using std::in_place_t;
+using std::in_place_type_t;
+using std::in_place_index_t;
+
+#define nonstd_lite_in_place_t( T) std::in_place_t
+#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
+#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
+
+#define nonstd_lite_in_place( T) std::in_place_t{}
+#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
+#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
+
+} // namespace nonstd
+
+#else // optional_CPP17_OR_GREATER
+
+#include <cstddef>
+
+namespace nonstd {
+namespace detail {
+
+template< class T >
+struct in_place_type_tag {};
+
+template< std::size_t K >
+struct in_place_index_tag {};
+
+} // namespace detail
+
+struct in_place_t {};
+
+template< class T >
+inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
+{
+ return in_place_t();
+}
+
+template< std::size_t K >
+inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
+{
+ return in_place_t();
+}
+
+template< class T >
+inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
+{
+ return in_place_t();
+}
+
+template< std::size_t K >
+inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
+{
+ return in_place_t();
+}
+
+// mimic templated typedef:
+
+#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
+#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
+#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
+
+#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
+#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
+#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
+
+} // namespace nonstd
+
+#endif // optional_CPP17_OR_GREATER
+#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
+
+//
+// Using std::optional:
+//
+
+#if optional_USES_STD_OPTIONAL
+
+#include <optional>
+
+namespace nonstd {
+
+ using std::optional;
+ using std::bad_optional_access;
+ using std::hash;
+
+ using std::nullopt;
+ using std::nullopt_t;
+
+ using std::operator==;
+ using std::operator!=;
+ using std::operator<;
+ using std::operator<=;
+ using std::operator>;
+ using std::operator>=;
+ using std::make_optional;
+ using std::swap;
+}
+
+#else // optional_USES_STD_OPTIONAL
+
+#include <cassert>
+#include <utility>
+
+// optional-lite alignment configuration:
+
+#ifndef optional_CONFIG_MAX_ALIGN_HACK
+# define optional_CONFIG_MAX_ALIGN_HACK 0
+#endif
+
+#ifndef optional_CONFIG_ALIGN_AS
+// no default, used in #if defined()
+#endif
+
+#ifndef optional_CONFIG_ALIGN_AS_FALLBACK
+# define optional_CONFIG_ALIGN_AS_FALLBACK double
+#endif
+
+// Compiler warning suppression:
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wundef"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wundef"
+#elif defined(_MSC_VER )
+# pragma warning( push )
+#endif
+
+// half-open range [lo..hi):
+#define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Compiler versions:
+//
+// MSVC++ 6.0 _MSC_VER == 1200 optional_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
+// MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
+// MSVC++ 7.1 _MSC_VER == 1310 optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
+// MSVC++ 8.0 _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
+// MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
+// MSVC++ 14.2 _MSC_VER >= 1920 optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
+
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define optional_COMPILER_MSVC_VER (_MSC_VER )
+# define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define optional_COMPILER_MSVC_VER 0
+# define optional_COMPILER_MSVC_VERSION 0
+#endif
+
+#define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) )
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define optional_COMPILER_GNUC_VERSION 0
+#endif
+
+#if defined(__clang__)
+# define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define optional_COMPILER_CLANG_VERSION 0
+#endif
+
+#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
+# pragma warning( disable: 4345 ) // initialization behavior changed
+#endif
+
+#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
+# pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const'
+#endif
+
+// Presence of language and library features:
+
+#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
+
+#ifdef _HAS_CPP0X
+# define optional_HAS_CPP0X _HAS_CPP0X
+#else
+# define optional_HAS_CPP0X 0
+#endif
+
+// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
+
+#if optional_COMPILER_MSVC_VER >= 1900
+# undef optional_CPP11_OR_GREATER
+# define optional_CPP11_OR_GREATER 1
+#endif
+
+#define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
+#define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
+#define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
+#define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
+#define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
+#define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
+
+#define optional_CPP14_000 (optional_CPP14_OR_GREATER)
+#define optional_CPP17_000 (optional_CPP17_OR_GREATER)
+
+// clang >= 2.9, gcc >= 4.9, msvc >= vc14.0/1900 (vs15):
+#define optional_CPP11_140_C290_G490 ((optional_CPP11_OR_GREATER_ && (optional_COMPILER_CLANG_VERSION >= 290 || optional_COMPILER_GNUC_VERSION >= 490)) || (optional_COMPILER_MSVC_VER >= 1900))
+
+// clang >= 3.5, msvc >= vc11 (vs12):
+#define optional_CPP11_110_C350 ( optional_CPP11_110 && !optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) )
+
+// clang >= 3.5, gcc >= 5.0, msvc >= vc11 (vs12):
+#define optional_CPP11_110_C350_G500 \
+ ( optional_CPP11_110 && \
+ !( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \
+ || optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) )
+
+// Presence of C++11 language features:
+
+#define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
+#define optional_HAVE_IS_DEFAULT optional_CPP11_140
+#define optional_HAVE_NOEXCEPT optional_CPP11_140
+#define optional_HAVE_NULLPTR optional_CPP11_100
+#define optional_HAVE_REF_QUALIFIER optional_CPP11_140_C290_G490
+#define optional_HAVE_STATIC_ASSERT optional_CPP11_110
+#define optional_HAVE_INITIALIZER_LIST optional_CPP11_140
+
+// Presence of C++14 language features:
+
+#define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
+
+// Presence of C++17 language features:
+
+#define optional_HAVE_NODISCARD optional_CPP17_000
+
+// Presence of C++ library features:
+
+#define optional_HAVE_CONDITIONAL optional_CPP11_120
+#define optional_HAVE_REMOVE_CV optional_CPP11_120
+#define optional_HAVE_TYPE_TRAITS optional_CPP11_90
+
+#define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
+#define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
+
+#define optional_HAVE_IS_ASSIGNABLE optional_CPP11_110_C350
+#define optional_HAVE_IS_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350
+#define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE optional_CPP11_110_C350
+#define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350
+#define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE optional_CPP11_110_C350_G500
+#define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350_G500
+
+// C++ feature usage:
+
+#if optional_HAVE( CONSTEXPR_11 )
+# define optional_constexpr constexpr
+#else
+# define optional_constexpr /*constexpr*/
+#endif
+
+#if optional_HAVE( IS_DEFAULT )
+# define optional_is_default = default;
+#else
+# define optional_is_default {}
+#endif
+
+#if optional_HAVE( CONSTEXPR_14 )
+# define optional_constexpr14 constexpr
+#else
+# define optional_constexpr14 /*constexpr*/
+#endif
+
+#if optional_HAVE( NODISCARD )
+# define optional_nodiscard [[nodiscard]]
+#else
+# define optional_nodiscard /*[[nodiscard]]*/
+#endif
+
+#if optional_HAVE( NOEXCEPT )
+# define optional_noexcept noexcept
+#else
+# define optional_noexcept /*noexcept*/
+#endif
+
+#if optional_HAVE( NULLPTR )
+# define optional_nullptr nullptr
+#else
+# define optional_nullptr NULL
+#endif
+
+#if optional_HAVE( REF_QUALIFIER )
+// NOLINTNEXTLINE( bugprone-macro-parentheses )
+# define optional_ref_qual &
+# define optional_refref_qual &&
+#else
+# define optional_ref_qual /*&*/
+# define optional_refref_qual /*&&*/
+#endif
+
+#if optional_HAVE( STATIC_ASSERT )
+# define optional_static_assert(expr, text) static_assert(expr, text);
+#else
+# define optional_static_assert(expr, text) /*static_assert(expr, text);*/
+#endif
+
+// additional includes:
+
+#if optional_CONFIG_NO_EXCEPTIONS
+// already included: <cassert>
+#else
+# include <stdexcept>
+#endif
+
+#if optional_CPP11_OR_GREATER
+# include <functional>
+#endif
+
+#if optional_HAVE( INITIALIZER_LIST )
+# include <initializer_list>
+#endif
+
+#if optional_HAVE( TYPE_TRAITS )
+# include <type_traits>
+#elif optional_HAVE( TR1_TYPE_TRAITS )
+# include <tr1/type_traits>
+#endif
+
+// Method enabling
+
+#if optional_CPP11_OR_GREATER
+
+#define optional_REQUIRES_0(...) \
+ template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
+
+#define optional_REQUIRES_T(...) \
+ , typename std::enable_if< (__VA_ARGS__), int >::type = 0
+
+#define optional_REQUIRES_R(R, ...) \
+ typename std::enable_if< (__VA_ARGS__), R>::type
+
+#define optional_REQUIRES_A(...) \
+ , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
+
+#endif
+
+//
+// optional:
+//
+
+namespace nonstd { namespace optional_lite {
+
+namespace std11 {
+
+template< class T, T v > struct integral_constant { enum { value = v }; };
+template< bool B > struct bool_constant : integral_constant<bool, B>{};
+
+typedef bool_constant< true > true_type;
+typedef bool_constant< false > false_type;
+
+#if optional_CPP11_OR_GREATER
+ using std::move;
+#else
+ template< typename T > T & move( T & t ) { return t; }
+#endif
+
+#if optional_HAVE( CONDITIONAL )
+ using std::conditional;
+#else
+ template< bool B, typename T, typename F > struct conditional { typedef T type; };
+ template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
+#endif // optional_HAVE_CONDITIONAL
+
+#if optional_HAVE( IS_ASSIGNABLE )
+ using std::is_assignable;
+#else
+ template< class T, class U > struct is_assignable : std11::true_type{};
+#endif
+
+#if optional_HAVE( IS_MOVE_CONSTRUCTIBLE )
+ using std::is_move_constructible;
+#else
+ template< class T > struct is_move_constructible : std11::true_type{};
+#endif
+
+#if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE )
+ using std::is_nothrow_move_assignable;
+#else
+ template< class T > struct is_nothrow_move_assignable : std11::true_type{};
+#endif
+
+#if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE )
+ using std::is_nothrow_move_constructible;
+#else
+ template< class T > struct is_nothrow_move_constructible : std11::true_type{};
+#endif
+
+#if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE )
+ using std::is_trivially_copy_constructible;
+#else
+ template< class T > struct is_trivially_copy_constructible : std11::true_type{};
+#endif
+
+#if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE )
+ using std::is_trivially_move_constructible;
+#else
+ template< class T > struct is_trivially_move_constructible : std11::true_type{};
+#endif
+
+} // namespace std11
+
+#if optional_CPP11_OR_GREATER
+
+/// type traits C++17:
+
+namespace std17 {
+
+#if optional_CPP17_OR_GREATER
+
+using std::is_swappable;
+using std::is_nothrow_swappable;
+
+#elif optional_CPP11_OR_GREATER
+
+namespace detail {
+
+using std::swap;
+
+struct is_swappable
+{
+ template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
+ static std11::true_type test( int /*unused*/ );
+
+ template< typename >
+ static std11::false_type test(...);
+};
+
+struct is_nothrow_swappable
+{
+ // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
+
+ template< typename T >
+ static constexpr bool satisfies()
+ {
+ return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
+ }
+
+ template< typename T >
+ static auto test( int /*unused*/ ) -> std11::integral_constant<bool, satisfies<T>()>{}
+
+ template< typename >
+ static auto test(...) -> std11::false_type;
+};
+
+} // namespace detail
+
+// is [nothow] swappable:
+
+template< typename T >
+struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
+
+template< typename T >
+struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
+
+#endif // optional_CPP17_OR_GREATER
+
+} // namespace std17
+
+/// type traits C++20:
+
+namespace std20 {
+
+template< typename T >
+struct remove_cvref
+{
+ typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
+};
+
+} // namespace std20
+
+#endif // optional_CPP11_OR_GREATER
+
+/// class optional
+
+template< typename T >
+class optional;
+
+namespace detail {
+
+// C++11 emulation:
+
+struct nulltype{};
+
+template< typename Head, typename Tail >
+struct typelist
+{
+ typedef Head head;
+ typedef Tail tail;
+};
+
+#if optional_CONFIG_MAX_ALIGN_HACK
+
+// Max align, use most restricted type for alignment:
+
+#define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
+#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
+#define optional_UNIQUE3( name, line ) name ## line
+
+#define optional_ALIGN_TYPE( type ) \
+ type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
+
+template< typename T >
+struct struct_t { T _; };
+
+union max_align_t
+{
+ optional_ALIGN_TYPE( char );
+ optional_ALIGN_TYPE( short int );
+ optional_ALIGN_TYPE( int );
+ optional_ALIGN_TYPE( long int );
+ optional_ALIGN_TYPE( float );
+ optional_ALIGN_TYPE( double );
+ optional_ALIGN_TYPE( long double );
+ optional_ALIGN_TYPE( char * );
+ optional_ALIGN_TYPE( short int * );
+ optional_ALIGN_TYPE( int * );
+ optional_ALIGN_TYPE( long int * );
+ optional_ALIGN_TYPE( float * );
+ optional_ALIGN_TYPE( double * );
+ optional_ALIGN_TYPE( long double * );
+ optional_ALIGN_TYPE( void * );
+
+#ifdef HAVE_LONG_LONG
+ optional_ALIGN_TYPE( long long );
+#endif
+
+ struct Unknown;
+
+ Unknown ( * optional_UNIQUE(_) )( Unknown );
+ Unknown * Unknown::* optional_UNIQUE(_);
+ Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
+
+ struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
+ struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
+ struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
+};
+
+#undef optional_UNIQUE
+#undef optional_UNIQUE2
+#undef optional_UNIQUE3
+
+#undef optional_ALIGN_TYPE
+
+#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
+
+// Use user-specified type for alignment:
+
+#define optional_ALIGN_AS( unused ) \
+ optional_CONFIG_ALIGN_AS
+
+#else // optional_CONFIG_MAX_ALIGN_HACK
+
+// Determine POD type to use for alignment:
+
+#define optional_ALIGN_AS( to_align ) \
+ typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
+
+template< typename T >
+struct alignment_of;
+
+template< typename T >
+struct alignment_of_hack
+{
+ char c;
+ T t;
+ alignment_of_hack();
+};
+
+template< size_t A, size_t S >
+struct alignment_logic
+{
+ enum { value = A < S ? A : S };
+};
+
+template< typename T >
+struct alignment_of
+{
+ enum { value = alignment_logic<
+ sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
+};
+
+template< typename List, size_t N >
+struct type_of_size
+{
+ typedef typename std11::conditional<
+ N == sizeof( typename List::head ),
+ typename List::head,
+ typename type_of_size<typename List::tail, N >::type >::type type;
+};
+
+template< size_t N >
+struct type_of_size< nulltype, N >
+{
+ typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
+};
+
+template< typename T>
+struct struct_t { T _; };
+
+#define optional_ALIGN_TYPE( type ) \
+ typelist< type , typelist< struct_t< type >
+
+struct Unknown;
+
+typedef
+ optional_ALIGN_TYPE( char ),
+ optional_ALIGN_TYPE( short ),
+ optional_ALIGN_TYPE( int ),
+ optional_ALIGN_TYPE( long ),
+ optional_ALIGN_TYPE( float ),
+ optional_ALIGN_TYPE( double ),
+ optional_ALIGN_TYPE( long double ),
+
+ optional_ALIGN_TYPE( char *),
+ optional_ALIGN_TYPE( short * ),
+ optional_ALIGN_TYPE( int * ),
+ optional_ALIGN_TYPE( long * ),
+ optional_ALIGN_TYPE( float * ),
+ optional_ALIGN_TYPE( double * ),
+ optional_ALIGN_TYPE( long double * ),
+
+ optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
+ optional_ALIGN_TYPE( Unknown * Unknown::* ),
+ optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
+
+ nulltype
+ > > > > > > > > > > > > > >
+ > > > > > > > > > > > > > >
+ > > > > > >
+ alignment_types;
+
+#undef optional_ALIGN_TYPE
+
+#endif // optional_CONFIG_MAX_ALIGN_HACK
+
+/// C++03 constructed union to hold value.
+
+template< typename T >
+union storage_t
+{
+//private:
+// template< typename > friend class optional;
+
+ typedef T value_type;
+
+ storage_t() optional_is_default
+
+ explicit storage_t( value_type const & v )
+ {
+ construct_value( v );
+ }
+
+ void construct_value( value_type const & v )
+ {
+ ::new( value_ptr() ) value_type( v );
+ }
+
+#if optional_CPP11_OR_GREATER
+
+ explicit storage_t( value_type && v )
+ {
+ construct_value( std::move( v ) );
+ }
+
+ void construct_value( value_type && v )
+ {
+ ::new( value_ptr() ) value_type( std::move( v ) );
+ }
+
+ template< class... Args >
+ storage_t( nonstd_lite_in_place_t(T), Args&&... args )
+ {
+ emplace( std::forward<Args>(args)... );
+ }
+
+ template< class... Args >
+ void emplace( Args&&... args )
+ {
+ ::new( value_ptr() ) value_type( std::forward<Args>(args)... );
+ }
+
+ template< class U, class... Args >
+ void emplace( std::initializer_list<U> il, Args&&... args )
+ {
+ ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
+ }
+
+#endif
+
+ void destruct_value()
+ {
+ value_ptr()->~T();
+ }
+
+ optional_nodiscard value_type const * value_ptr() const
+ {
+ return as<value_type>();
+ }
+
+ value_type * value_ptr()
+ {
+ return as<value_type>();
+ }
+
+ optional_nodiscard value_type const & value() const optional_ref_qual
+ {
+ return * value_ptr();
+ }
+
+ value_type & value() optional_ref_qual
+ {
+ return * value_ptr();
+ }
+
+#if optional_HAVE( REF_QUALIFIER )
+
+ optional_nodiscard value_type const && value() const optional_refref_qual
+ {
+ return std::move( value() );
+ }
+
+ value_type && value() optional_refref_qual
+ {
+ return std::move( value() );
+ }
+
+#endif
+
+#if optional_CPP11_OR_GREATER
+
+ using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
+ aligned_storage_t data;
+
+#elif optional_CONFIG_MAX_ALIGN_HACK
+
+ typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
+
+ max_align_t hack;
+ aligned_storage_t data;
+
+#else
+ typedef optional_ALIGN_AS(value_type) align_as_type;
+
+ typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
+ aligned_storage_t data;
+
+# undef optional_ALIGN_AS
+
+#endif // optional_CONFIG_MAX_ALIGN_HACK
+
+ optional_nodiscard void * ptr() optional_noexcept
+ {
+ return &data;
+ }
+
+ optional_nodiscard void const * ptr() const optional_noexcept
+ {
+ return &data;
+ }
+
+ template <typename U>
+ optional_nodiscard U * as()
+ {
+ return reinterpret_cast<U*>( ptr() );
+ }
+
+ template <typename U>
+ optional_nodiscard U const * as() const
+ {
+ return reinterpret_cast<U const *>( ptr() );
+ }
+};
+
+} // namespace detail
+
+/// disengaged state tag
+
+struct nullopt_t
+{
+ struct init{};
+ explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
+};
+
+#if optional_HAVE( CONSTEXPR_11 )
+constexpr nullopt_t nullopt{ nullopt_t::init{} };
+#else
+// extra parenthesis to prevent the most vexing parse:
+const nullopt_t nullopt(( nullopt_t::init() ));
+#endif
+
+/// optional access error
+
+#if ! optional_CONFIG_NO_EXCEPTIONS
+
+class bad_optional_access : public std::logic_error
+{
+public:
+ explicit bad_optional_access()
+ : logic_error( "bad optional access" ) {}
+};
+
+#endif //optional_CONFIG_NO_EXCEPTIONS
+
+/// optional
+
+template< typename T>
+class optional
+{
+ optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value ),
+ "T in optional<T> must not be of type 'nullopt_t'.")
+
+ optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, in_place_t>::value ),
+ "T in optional<T> must not be of type 'in_place_t'.")
+
+ optional_static_assert(( std::is_object<T>::value && std::is_destructible<T>::value && !std::is_array<T>::value ),
+ "T in optional<T> must meet the Cpp17Destructible requirements.")
+
+private:
+ template< typename > friend class optional;
+
+ typedef void (optional::*safe_bool)() const;
+
+public:
+ typedef T value_type;
+
+ // x.x.3.1, constructors
+
+ // 1a - default construct
+ optional_constexpr optional() optional_noexcept
+ : has_value_( false )
+ , contained()
+ {}
+
+ // 1b - construct explicitly empty
+ // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
+ optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
+ : has_value_( false )
+ , contained()
+ {}
+
+ // 2 - copy-construct
+#if optional_CPP11_OR_GREATER
+ // template< typename U = T
+ // optional_REQUIRES_T(
+ // std::is_copy_constructible<U>::value
+ // || std11::is_trivially_copy_constructible<U>::value
+ // )
+ // >
+#endif
+ optional_constexpr14 optional( optional const & other )
+ : has_value_( other.has_value() )
+ {
+ if ( other.has_value() )
+ {
+ contained.construct_value( other.contained.value() );
+ }
+ }
+
+#if optional_CPP11_OR_GREATER
+
+ // 3 (C++11) - move-construct from optional
+ template< typename U = T
+ optional_REQUIRES_T(
+ std11::is_move_constructible<U>::value
+ || std11::is_trivially_move_constructible<U>::value
+ )
+ >
+ optional_constexpr14 optional( optional && other )
+ // NOLINTNEXTLINE( performance-noexcept-move-constructor )
+ noexcept( std11::is_nothrow_move_constructible<T>::value )
+ : has_value_( other.has_value() )
+ {
+ if ( other.has_value() )
+ {
+ contained.construct_value( std::move( other.contained.value() ) );
+ }
+ }
+
+ // 4a (C++11) - explicit converting copy-construct from optional
+ template< typename U
+ optional_REQUIRES_T(
+ std::is_constructible<T, U const &>::value
+ && !std::is_constructible<T, optional<U> & >::value
+ && !std::is_constructible<T, optional<U> && >::value
+ && !std::is_constructible<T, optional<U> const & >::value
+ && !std::is_constructible<T, optional<U> const && >::value
+ && !std::is_convertible< optional<U> & , T>::value
+ && !std::is_convertible< optional<U> && , T>::value
+ && !std::is_convertible< optional<U> const & , T>::value
+ && !std::is_convertible< optional<U> const &&, T>::value
+ && !std::is_convertible< U const & , T>::value /*=> explicit */
+ )
+ >
+ explicit optional( optional<U> const & other )
+ : has_value_( other.has_value() )
+ {
+ if ( other.has_value() )
+ {
+ contained.construct_value( T{ other.contained.value() } );
+ }
+ }
+#endif // optional_CPP11_OR_GREATER
+
+ // 4b (C++98 and later) - non-explicit converting copy-construct from optional
+ template< typename U
+#if optional_CPP11_OR_GREATER
+ optional_REQUIRES_T(
+ std::is_constructible<T, U const &>::value
+ && !std::is_constructible<T, optional<U> & >::value
+ && !std::is_constructible<T, optional<U> && >::value
+ && !std::is_constructible<T, optional<U> const & >::value
+ && !std::is_constructible<T, optional<U> const && >::value
+ && !std::is_convertible< optional<U> & , T>::value
+ && !std::is_convertible< optional<U> && , T>::value
+ && !std::is_convertible< optional<U> const & , T>::value
+ && !std::is_convertible< optional<U> const &&, T>::value
+ && std::is_convertible< U const & , T>::value /*=> non-explicit */
+ )
+#endif // optional_CPP11_OR_GREATER
+ >
+ // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
+ /*non-explicit*/ optional( optional<U> const & other )
+ : has_value_( other.has_value() )
+ {
+ if ( other.has_value() )
+ {
+ contained.construct_value( other.contained.value() );
+ }
+ }
+
+#if optional_CPP11_OR_GREATER
+
+ // 5a (C++11) - explicit converting move-construct from optional
+ template< typename U
+ optional_REQUIRES_T(
+ std::is_constructible<T, U &&>::value
+ && !std::is_constructible<T, optional<U> & >::value
+ && !std::is_constructible<T, optional<U> && >::value
+ && !std::is_constructible<T, optional<U> const & >::value
+ && !std::is_constructible<T, optional<U> const && >::value
+ && !std::is_convertible< optional<U> & , T>::value
+ && !std::is_convertible< optional<U> && , T>::value
+ && !std::is_convertible< optional<U> const & , T>::value
+ && !std::is_convertible< optional<U> const &&, T>::value
+ && !std::is_convertible< U &&, T>::value /*=> explicit */
+ )
+ >
+ explicit optional( optional<U> && other
+ )
+ : has_value_( other.has_value() )
+ {
+ if ( other.has_value() )
+ {
+ contained.construct_value( T{ std::move( other.contained.value() ) } );
+ }
+ }
+
+ // 5a (C++11) - non-explicit converting move-construct from optional
+ template< typename U
+ optional_REQUIRES_T(
+ std::is_constructible<T, U &&>::value
+ && !std::is_constructible<T, optional<U> & >::value
+ && !std::is_constructible<T, optional<U> && >::value
+ && !std::is_constructible<T, optional<U> const & >::value
+ && !std::is_constructible<T, optional<U> const && >::value
+ && !std::is_convertible< optional<U> & , T>::value
+ && !std::is_convertible< optional<U> && , T>::value
+ && !std::is_convertible< optional<U> const & , T>::value
+ && !std::is_convertible< optional<U> const &&, T>::value
+ && std::is_convertible< U &&, T>::value /*=> non-explicit */
+ )
+ >
+ // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
+ /*non-explicit*/ optional( optional<U> && other )
+ : has_value_( other.has_value() )
+ {
+ if ( other.has_value() )
+ {
+ contained.construct_value( std::move( other.contained.value() ) );
+ }
+ }
+
+ // 6 (C++11) - in-place construct
+ template< typename... Args
+ optional_REQUIRES_T(
+ std::is_constructible<T, Args&&...>::value
+ )
+ >
+ optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
+ : has_value_( true )
+ , contained( in_place, std::forward<Args>(args)... )
+ {}
+
+ // 7 (C++11) - in-place construct, initializer-list
+ template< typename U, typename... Args
+ optional_REQUIRES_T(
+ std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
+ )
+ >
+ optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
+ : has_value_( true )
+ , contained( T( il, std::forward<Args>(args)...) )
+ {}
+
+ // 8a (C++11) - explicit move construct from value
+ template< typename U = T
+ optional_REQUIRES_T(
+ std::is_constructible<T, U&&>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
+ && !std::is_convertible<U&&, T>::value /*=> explicit */
+ )
+ >
+ optional_constexpr explicit optional( U && value )
+ : has_value_( true )
+ , contained( nonstd_lite_in_place(T), std::forward<U>( value ) )
+ {}
+
+ // 8b (C++11) - non-explicit move construct from value
+ template< typename U = T
+ optional_REQUIRES_T(
+ std::is_constructible<T, U&&>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
+ && std::is_convertible<U&&, T>::value /*=> non-explicit */
+ )
+ >
+ // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
+ optional_constexpr /*non-explicit*/ optional( U && value )
+ : has_value_( true )
+ , contained( nonstd_lite_in_place(T), std::forward<U>( value ) )
+ {}
+
+#else // optional_CPP11_OR_GREATER
+
+ // 8 (C++98)
+ optional( value_type const & value )
+ : has_value_( true )
+ , contained( value )
+ {}
+
+#endif // optional_CPP11_OR_GREATER
+
+ // x.x.3.2, destructor
+
+ ~optional()
+ {
+ if ( has_value() )
+ {
+ contained.destruct_value();
+ }
+ }
+
+ // x.x.3.3, assignment
+
+ // 1 (C++98and later) - assign explicitly empty
+ optional & operator=( nullopt_t /*unused*/) optional_noexcept
+ {
+ reset();
+ return *this;
+ }
+
+ // 2 (C++98and later) - copy-assign from optional
+#if optional_CPP11_OR_GREATER
+ // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
+ optional_REQUIRES_R(
+ optional &,
+ true
+// std::is_copy_constructible<T>::value
+// && std::is_copy_assignable<T>::value
+ )
+ operator=( optional const & other )
+ noexcept(
+ std11::is_nothrow_move_assignable<T>::value
+ && std11::is_nothrow_move_constructible<T>::value
+ )
+#else
+ optional & operator=( optional const & other )
+#endif
+ {
+ if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
+ else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); }
+ else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; }
+ return *this;
+ }
+
+#if optional_CPP11_OR_GREATER
+
+ // 3 (C++11) - move-assign from optional
+ // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
+ optional_REQUIRES_R(
+ optional &,
+ true
+// std11::is_move_constructible<T>::value
+// && std::is_move_assignable<T>::value
+ )
+ operator=( optional && other ) noexcept
+ {
+ if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
+ else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); }
+ else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); }
+ return *this;
+ }
+
+ // 4 (C++11) - move-assign from value
+ template< typename U = T >
+ // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
+ optional_REQUIRES_R(
+ optional &,
+ std::is_constructible<T , U>::value
+ && std11::is_assignable<T&, U>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
+ && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
+ )
+ operator=( U && value )
+ {
+ if ( has_value() )
+ {
+ contained.value() = std::forward<U>( value );
+ }
+ else
+ {
+ initialize( T( std::forward<U>( value ) ) );
+ }
+ return *this;
+ }
+
+#else // optional_CPP11_OR_GREATER
+
+ // 4 (C++98) - copy-assign from value
+ template< typename U /*= T*/ >
+ optional & operator=( U const & value )
+ {
+ if ( has_value() ) contained.value() = value;
+ else initialize( T( value ) );
+ return *this;
+ }
+
+#endif // optional_CPP11_OR_GREATER
+
+ // 5 (C++98 and later) - converting copy-assign from optional
+ template< typename U >
+#if optional_CPP11_OR_GREATER
+ // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
+ optional_REQUIRES_R(
+ optional&,
+ std::is_constructible< T , U const &>::value
+ && std11::is_assignable< T&, U const &>::value
+ && !std::is_constructible<T, optional<U> & >::value
+ && !std::is_constructible<T, optional<U> && >::value
+ && !std::is_constructible<T, optional<U> const & >::value
+ && !std::is_constructible<T, optional<U> const && >::value
+ && !std::is_convertible< optional<U> & , T>::value
+ && !std::is_convertible< optional<U> && , T>::value
+ && !std::is_convertible< optional<U> const & , T>::value
+ && !std::is_convertible< optional<U> const &&, T>::value
+ && !std11::is_assignable< T&, optional<U> & >::value
+ && !std11::is_assignable< T&, optional<U> && >::value
+ && !std11::is_assignable< T&, optional<U> const & >::value
+ && !std11::is_assignable< T&, optional<U> const && >::value
+ )
+#else
+ optional&
+#endif // optional_CPP11_OR_GREATER
+ operator=( optional<U> const & other )
+ {
+ return *this = optional( other );
+ }
+
+#if optional_CPP11_OR_GREATER
+
+ // 6 (C++11) - converting move-assign from optional
+ template< typename U >
+ // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
+ optional_REQUIRES_R(
+ optional&,
+ std::is_constructible< T , U>::value
+ && std11::is_assignable< T&, U>::value
+ && !std::is_constructible<T, optional<U> & >::value
+ && !std::is_constructible<T, optional<U> && >::value
+ && !std::is_constructible<T, optional<U> const & >::value
+ && !std::is_constructible<T, optional<U> const && >::value
+ && !std::is_convertible< optional<U> & , T>::value
+ && !std::is_convertible< optional<U> && , T>::value
+ && !std::is_convertible< optional<U> const & , T>::value
+ && !std::is_convertible< optional<U> const &&, T>::value
+ && !std11::is_assignable< T&, optional<U> & >::value
+ && !std11::is_assignable< T&, optional<U> && >::value
+ && !std11::is_assignable< T&, optional<U> const & >::value
+ && !std11::is_assignable< T&, optional<U> const && >::value
+ )
+ operator=( optional<U> && other )
+ {
+ return *this = optional( std::move( other ) );
+ }
+
+ // 7 (C++11) - emplace
+ template< typename... Args
+ optional_REQUIRES_T(
+ std::is_constructible<T, Args&&...>::value
+ )
+ >
+ T& emplace( Args&&... args )
+ {
+ *this = nullopt;
+ contained.emplace( std::forward<Args>(args)... );
+ has_value_ = true;
+ return contained.value();
+ }
+
+ // 8 (C++11) - emplace, initializer-list
+ template< typename U, typename... Args
+ optional_REQUIRES_T(
+ std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
+ )
+ >
+ T& emplace( std::initializer_list<U> il, Args&&... args )
+ {
+ *this = nullopt;
+ contained.emplace( il, std::forward<Args>(args)... );
+ has_value_ = true;
+ return contained.value();
+ }
+
+#endif // optional_CPP11_OR_GREATER
+
+ // x.x.3.4, swap
+
+ void swap( optional & other )
+#if optional_CPP11_OR_GREATER
+ noexcept(
+ std11::is_nothrow_move_constructible<T>::value
+ && std17::is_nothrow_swappable<T>::value
+ )
+#endif
+ {
+ using std::swap;
+ if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); }
+ else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); }
+ else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); }
+ }
+
+ // x.x.3.5, observers
+
+ optional_constexpr value_type const * operator ->() const
+ {
+ return assert( has_value() ),
+ contained.value_ptr();
+ }
+
+ optional_constexpr14 value_type * operator ->()
+ {
+ return assert( has_value() ),
+ contained.value_ptr();
+ }
+
+ optional_constexpr value_type const & operator *() const optional_ref_qual
+ {
+ return assert( has_value() ),
+ contained.value();
+ }
+
+ optional_constexpr14 value_type & operator *() optional_ref_qual
+ {
+ return assert( has_value() ),
+ contained.value();
+ }
+
+#if optional_HAVE( REF_QUALIFIER )
+
+ optional_constexpr value_type const && operator *() const optional_refref_qual
+ {
+ return std::move( **this );
+ }
+
+ optional_constexpr14 value_type && operator *() optional_refref_qual
+ {
+ return std::move( **this );
+ }
+
+#endif
+
+#if optional_CPP11_OR_GREATER
+ optional_constexpr explicit operator bool() const optional_noexcept
+ {
+ return has_value();
+ }
+#else
+ optional_constexpr operator safe_bool() const optional_noexcept
+ {
+ return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
+ }
+#endif
+
+ // NOLINTNEXTLINE( modernize-use-nodiscard )
+ /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
+ {
+ return has_value_;
+ }
+
+ // NOLINTNEXTLINE( modernize-use-nodiscard )
+ /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
+ {
+#if optional_CONFIG_NO_EXCEPTIONS
+ assert( has_value() );
+#else
+ if ( ! has_value() )
+ {
+ throw bad_optional_access();
+ }
+#endif
+ return contained.value();
+ }
+
+ optional_constexpr14 value_type & value() optional_ref_qual
+ {
+#if optional_CONFIG_NO_EXCEPTIONS
+ assert( has_value() );
+#else
+ if ( ! has_value() )
+ {
+ throw bad_optional_access();
+ }
+#endif
+ return contained.value();
+ }
+
+#if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
+
+ // NOLINTNEXTLINE( modernize-use-nodiscard )
+ /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual
+ {
+ return std::move( value() );
+ }
+
+ optional_constexpr14 value_type && value() optional_refref_qual
+ {
+ return std::move( value() );
+ }
+
+#endif
+
+#if optional_HAVE( REF_QUALIFIER )
+
+ template< typename U >
+ optional_constexpr value_type value_or( U && v ) const optional_ref_qual
+ {
+ return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
+ }
+
+ template< typename U >
+ optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
+ {
+#if optional_COMPILER_CLANG_VERSION
+ return has_value() ? /*std::move*/( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
+#else
+ return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
+#endif
+ }
+
+#else
+
+ template< typename U >
+ optional_constexpr value_type value_or( U const & v ) const
+ {
+ return has_value() ? contained.value() : static_cast<value_type>( v );
+ }
+
+#endif // optional_HAVE( REF_QUALIFIER )
+
+#if !optional_CONFIG_NO_EXTENSIONS
+#if optional_HAVE( REF_QUALIFIER )
+
+ template< typename F >
+ optional_constexpr value_type value_or_eval( F f ) const &
+ {
+ return has_value() ? contained.value() : f();
+ }
+
+ template< typename F >
+ optional_constexpr14 value_type value_or_eval( F f ) &&
+ {
+ if ( has_value() )
+ {
+ return std::move( contained.value() );
+ }
+ else
+ {
+ return f();
+ }
+ }
+
+#else
+
+ template< typename F >
+ optional_constexpr value_type value_or_eval( F f ) const
+ {
+ return has_value() ? contained.value() : f();
+ }
+
+#endif // optional_HAVE( REF_QUALIFIER )
+#endif // !optional_CONFIG_NO_EXTENSIONS
+
+ // x.x.3.6, modifiers
+
+ void reset() optional_noexcept
+ {
+ if ( has_value() )
+ {
+ contained.destruct_value();
+ }
+
+ has_value_ = false;
+ }
+
+private:
+ void this_type_does_not_support_comparisons() const {}
+
+ template< typename V >
+ void initialize( V const & value )
+ {
+ assert( ! has_value() );
+ contained.construct_value( value );
+ has_value_ = true;
+ }
+
+#if optional_CPP11_OR_GREATER
+ template< typename V >
+ void initialize( V && value )
+ {
+ assert( ! has_value() );
+ contained.construct_value( std::move( value ) );
+ has_value_ = true;
+ }
+
+#endif
+
+private:
+ bool has_value_;
+ detail::storage_t< value_type > contained;
+
+};
+
+// Relational operators
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
+{
+ return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
+{
+ return !(x == y);
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
+{
+ return (!y) ? false : (!x) ? true : *x < *y;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
+{
+ return (y < x);
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
+{
+ return !(y < x);
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
+{
+ return !(x < y);
+}
+
+// Comparison with nullopt
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
+{
+ return (!x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
+{
+ return (!x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
+{
+ return bool(x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
+{
+ return bool(x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
+{
+ return false;
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
+{
+ return bool(x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
+{
+ return (!x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
+{
+ return true;
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
+{
+ return bool(x);
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
+{
+ return false;
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
+{
+ return true;
+}
+
+template< typename T >
+optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
+{
+ return (!x);
+}
+
+// Comparison with T
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v )
+{
+ return bool(x) ? *x == v : false;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x )
+{
+ return bool(x) ? v == *x : false;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v )
+{
+ return bool(x) ? *x != v : true;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x )
+{
+ return bool(x) ? v != *x : true;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v )
+{
+ return bool(x) ? *x < v : true;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x )
+{
+ return bool(x) ? v < *x : false;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v )
+{
+ return bool(x) ? *x <= v : true;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x )
+{
+ return bool(x) ? v <= *x : false;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v )
+{
+ return bool(x) ? *x > v : false;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x )
+{
+ return bool(x) ? v > *x : true;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v )
+{
+ return bool(x) ? *x >= v : false;
+}
+
+template< typename T, typename U >
+optional_nodiscard optional_constexpr bool operator>=( U const & v, optional<T> const & x )
+{
+ return bool(x) ? v >= *x : true;
+}
+
+// Specialized algorithms
+
+template< typename T
+#if optional_CPP11_OR_GREATER
+ optional_REQUIRES_T(
+ std11::is_move_constructible<T>::value
+ && std17::is_swappable<T>::value )
+#endif
+>
+void swap( optional<T> & x, optional<T> & y )
+#if optional_CPP11_OR_GREATER
+ noexcept( noexcept( x.swap(y) ) )
+#endif
+{
+ x.swap( y );
+}
+
+#if optional_CPP11_OR_GREATER
+
+template< typename T >
+optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
+{
+ return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
+}
+
+template< typename T, typename...Args >
+optional_constexpr optional<T> make_optional( Args&&... args )
+{
+ return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
+}
+
+template< typename T, typename U, typename... Args >
+optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
+{
+ return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
+}
+
+#else
+
+template< typename T >
+optional<T> make_optional( T const & value )
+{
+ return optional<T>( value );
+}
+
+#endif // optional_CPP11_OR_GREATER
+
+} // namespace optional_lite
+
+using optional_lite::optional;
+using optional_lite::nullopt_t;
+using optional_lite::nullopt;
+
+#if ! optional_CONFIG_NO_EXCEPTIONS
+using optional_lite::bad_optional_access;
+#endif
+
+using optional_lite::make_optional;
+
+} // namespace nonstd
+
+#if optional_CPP11_OR_GREATER
+
+// specialize the std::hash algorithm:
+
+namespace std {
+
+template< class T >
+struct hash< nonstd::optional<T> >
+{
+public:
+ std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
+ {
+ return bool( v ) ? std::hash<T>{}( *v ) : 0;
+ }
+};
+
+} //namespace std
+
+#endif // optional_CPP11_OR_GREATER
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# pragma GCC diagnostic pop
+#elif defined(_MSC_VER )
+# pragma warning( pop )
+#endif
+
+#endif // optional_USES_STD_OPTIONAL
+
+#endif // NONSTD_OPTIONAL_LITE_HPP
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.cpp
new file mode 100644
index 0000000000..356d803b5d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.cpp
@@ -0,0 +1,214 @@
+#include "serializer.h"
+#include <stdexcept>
+#include <rapidjson/allocators.h>
+#include "json.h"
+
+
+
+//// Elementary types
+
+void JsonNull::swap(JsonNull& arg) noexcept
+{
+}
+
+
+void Reflect(Reader& visitor, uint8_t& value) {
+ if (!visitor.IsInt())
+ throw std::invalid_argument("uint8_t");
+ value = (uint8_t)visitor.GetInt();
+}
+void Reflect(Writer& visitor, uint8_t& value) {
+ visitor.Int(value);
+}
+
+void Reflect(Reader& visitor, short& value) {
+ if (!visitor.IsInt())
+ throw std::invalid_argument("short");
+ value = (short)visitor.GetInt();
+}
+void Reflect(Writer& visitor, short& value) {
+ visitor.Int(value);
+}
+
+void Reflect(Reader& visitor, unsigned short& value) {
+ if (!visitor.IsInt())
+ throw std::invalid_argument("unsigned short");
+ value = (unsigned short)visitor.GetInt();
+}
+void Reflect(Writer& visitor, unsigned short& value) {
+ visitor.Int(value);
+}
+
+void Reflect(Reader& visitor, int& value) {
+ if (!visitor.IsInt())
+ throw std::invalid_argument("int");
+ value = visitor.GetInt();
+}
+void Reflect(Writer& visitor, int& value) {
+ visitor.Int(value);
+}
+
+void Reflect(Reader& visitor, unsigned& value) {
+ if (!visitor.IsUint64())
+ throw std::invalid_argument("unsigned");
+ value = visitor.GetUint32();
+}
+void Reflect(Writer& visitor, unsigned& value) {
+ visitor.Uint32(value);
+}
+
+void Reflect(Reader& visitor, long& value) {
+ if (!visitor.IsInt64())
+ throw std::invalid_argument("long");
+ value = long(visitor.GetInt64());
+}
+void Reflect(Writer& visitor, long& value) {
+ visitor.Int64(value);
+}
+
+void Reflect(Reader& visitor, unsigned long& value) {
+ if (!visitor.IsUint64())
+ throw std::invalid_argument("unsigned long");
+ value = (unsigned long)visitor.GetUint64();
+}
+void Reflect(Writer& visitor, unsigned long& value) {
+ visitor.Uint64(value);
+}
+
+void Reflect(Reader& visitor, long long& value) {
+ if (!visitor.IsInt64())
+ throw std::invalid_argument("long long");
+ value = visitor.GetInt64();
+}
+void Reflect(Writer& visitor, long long& value) {
+ visitor.Int64(value);
+}
+
+void Reflect(Reader& visitor, unsigned long long& value) {
+ if (!visitor.IsUint64())
+ throw std::invalid_argument("unsigned long long");
+ value = visitor.GetUint64();
+}
+void Reflect(Writer& visitor, unsigned long long& value) {
+ visitor.Uint64(value);
+}
+
+void Reflect(Reader& visitor, double& value) {
+ if (!visitor.IsNumber())
+ throw std::invalid_argument("double");
+ value = visitor.GetDouble();
+}
+void Reflect(Writer& visitor, double& value) {
+ visitor.Double(value);
+}
+
+void Reflect(Reader& visitor, bool& value) {
+ if (!visitor.IsBool())
+ throw std::invalid_argument("bool");
+ value = visitor.GetBool();
+}
+void Reflect(Writer& visitor, bool& value) {
+ visitor.Bool(value);
+}
+
+void Reflect(Reader& visitor, std::string& value) {
+ if (!visitor.IsString())
+ throw std::invalid_argument("std::string");
+ value = visitor.GetString();
+}
+void Reflect(Writer& visitor, std::string& value) {
+ visitor.String(value.c_str(), (rapidjson::SizeType)value.size());
+}
+
+void Reflect(Reader& visitor, JsonNull& value) {
+ visitor.GetNull();
+}
+
+void Reflect(Writer& visitor, JsonNull& value) {
+ visitor.Null();
+}
+
+
+void Reflect(Reader& visitor, SerializeFormat& value) {
+ std::string fmt = visitor.GetString();
+ value = fmt[0] == 'm' ? SerializeFormat::MessagePack : SerializeFormat::Json;
+}
+
+void Reflect(Writer& visitor, SerializeFormat& value) {
+ switch (value) {
+ case SerializeFormat::Json:
+ visitor.String("json");
+ break;
+ case SerializeFormat::MessagePack:
+ visitor.String("msgpack");
+ break;
+ }
+}
+
+
+std::string JsonReader::ToString() const
+{
+ rapidjson::StringBuffer strBuf;
+ strBuf.Clear();
+ rapidjson::Writer<rapidjson::StringBuffer> writer(strBuf);
+ m_->Accept(writer);
+ std::string strJson = strBuf.GetString();
+ return strJson;
+}
+
+void JsonReader::IterMap(std::function<void(const char*, Reader&)> fn)
+{
+ path_.push_back("0");
+ for (auto& entry : m_->GetObject())
+ {
+ auto saved = m_;
+ m_ = &(entry.value);
+
+ fn(entry.name.GetString(), *this);
+ m_ = saved;
+ }
+ path_.pop_back();
+}
+
+ void JsonReader::IterArray(std::function<void(Reader&)> fn)
+{
+ if (!m_->IsArray())
+ throw std::invalid_argument("array");
+ // Use "0" to indicate any element for now.
+ path_.push_back("0");
+ for (auto& entry : m_->GetArray())
+ {
+ auto saved = m_;
+ m_ = &entry;
+ fn(*this);
+ m_ = saved;
+ }
+ path_.pop_back();
+}
+
+void JsonReader::DoMember(const char* name, std::function<void(Reader&)> fn)
+{
+ path_.push_back(name);
+ auto it = m_->FindMember(name);
+ if (it != m_->MemberEnd())
+ {
+ auto saved = m_;
+ m_ = &it->value;
+ fn(*this);
+ m_ = saved;
+ }
+ path_.pop_back();
+}
+
+std::string JsonReader::GetPath() const
+{
+ std::string ret;
+ for (auto& t : path_)
+ {
+ ret += '/';
+ ret += t;
+ }
+ ret.pop_back();
+ return ret;
+}
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.h
new file mode 100644
index 0000000000..10456f40b5
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/serializer.h
@@ -0,0 +1,378 @@
+#pragma once
+
+
+#include <macro_map.h>
+#ifdef boost
+#include "optional.hpp"
+#else
+#include <boost/optional.hpp>
+#endif
+#include <cassert>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <vector>
+#include <functional>
+#include <map>
+#include <algorithm>
+
+
+struct AbsolutePath;
+
+enum class SerializeFormat { Json, MessagePack };
+
+// A tag type that can be used to write `null` to json.
+struct JsonNull
+{
+ void swap(JsonNull& arg) noexcept;
+};
+
+
+
+class Reader {
+public:
+ virtual ~Reader() {}
+ virtual SerializeFormat Format() const = 0;
+
+ virtual bool IsBool() = 0;
+ virtual bool IsNull() = 0;
+ virtual bool IsArray() = 0;
+ virtual bool IsInt() = 0;
+ virtual bool IsInt64() = 0;
+ virtual bool IsUint64() = 0;
+ virtual bool IsDouble() = 0;
+ virtual bool IsNumber() = 0;
+ virtual bool IsString() = 0;
+
+ virtual void GetNull() = 0;
+ virtual bool GetBool() = 0;
+ virtual int GetInt() = 0;
+ virtual uint32_t GetUint32() = 0;
+ virtual int64_t GetInt64() = 0;
+ virtual uint64_t GetUint64() = 0;
+ virtual double GetDouble() = 0;
+ virtual std::string GetString() = 0;
+
+ virtual bool HasMember(const char* x) = 0;
+ virtual std::unique_ptr<Reader> operator[](const char* x) = 0;
+ virtual void IterMap( std::function<void(const char*, Reader&)> fn) = 0;
+ virtual void IterArray(std::function<void(Reader&)> fn) = 0;
+ virtual void DoMember(const char* name, std::function<void(Reader&)> fn) = 0;
+ virtual std::string ToString() const = 0;
+};
+
+
+
+class Writer {
+public:
+ virtual ~Writer() {}
+ virtual SerializeFormat Format() const = 0;
+
+ virtual void Null() = 0;
+ virtual void Bool(bool x) = 0;
+ virtual void Int(int x) = 0;
+ virtual void Uint32(uint32_t x) = 0;
+ virtual void Int64(int64_t x) = 0;
+ virtual void Uint64(uint64_t x) = 0;
+ virtual void Double(double x) = 0;
+ virtual void String(const char* x) = 0;
+ virtual void String(const char* x, size_t len) = 0;
+ virtual void StartArray(size_t) = 0;
+ virtual void EndArray() = 0;
+ virtual void StartObject() = 0;
+ virtual void EndObject() = 0;
+ virtual void Key(const char* name) = 0;
+};
+
+
+
+struct optionals_mandatory_tag {};
+
+#define REFLECT_MEMBER_START() ReflectMemberStart(visitor, value)
+#define REFLECT_MEMBER_END() ReflectMemberEnd(visitor, value);
+#define REFLECT_MEMBER_END1(value) ReflectMemberEnd(visitor, value);
+#define REFLECT_MEMBER(name) ReflectMember(visitor, #name, value.name)
+#define REFLECT_MEMBER_OPTIONALS(name) \
+ ReflectMember(visitor, #name, value.name, optionals_mandatory_tag{})
+#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value)
+
+#define MAKE_REFLECT_TYPE_PROXY(type_name) \
+ MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type<type_name>::type)
+#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
+ inline void Reflect(Reader& visitor, type& value) { \
+ as_type value0; \
+ ::Reflect(visitor, value0); \
+ value = static_cast<type>(value0); \
+ } \
+ inline void Reflect(Writer& visitor, type& value) { \
+ auto value0 = static_cast<as_type>(value); \
+ ::Reflect(visitor, value0); \
+ }
+
+#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name);
+#define _MAPPABLE_REFLECT_MEMBER_OPTIONALS(name) REFLECT_MEMBER_OPTIONALS(name);
+
+#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \
+ template <typename TVisitor> \
+ void Reflect(TVisitor& visitor, type& value) { \
+ REFLECT_MEMBER_START(); \
+ REFLECT_MEMBER_END(); \
+ }
+
+#define MAKE_REFLECT_STRUCT(type, ...) \
+ template <typename TVisitor> \
+ void Reflect(TVisitor& visitor, type& value) { \
+ REFLECT_MEMBER_START(); \
+ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \
+ REFLECT_MEMBER_END(); \
+ }
+
+
+#define _MAPPABLE_SWAP_MEMBER(name) std::swap(name,arg.name);
+
+#define MAKE_SWAP_METHOD(type, ...) \
+void swap(type& arg) noexcept{ \
+ MACRO_MAP(_MAPPABLE_SWAP_MEMBER, __VA_ARGS__) \
+}
+
+#define MAKE_REFLECT_STRUCT_OPTIONALS_MANDATORY(type, ...) \
+ template <typename TVisitor> \
+ void Reflect(TVisitor& visitor, type& value) { \
+ REFLECT_MEMBER_START(); \
+ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER_OPTIONALS, __VA_ARGS__) \
+ REFLECT_MEMBER_END(); \
+ }
+
+// clang-format off
+// Config has many fields, we need to support at least its number of fields.
+#define NUM_VA_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,N,...) N
+#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
+// clang-format on
+
+#define _MAPPABLE_REFLECT_ARRAY(name) Reflect(visitor, value.name);
+
+// Reflects the struct so it is serialized as an array instead of an object.
+// This currently only supports writers.
+#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
+ inline void Reflect(Writer& visitor, type& value) { \
+ visitor.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \
+ MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
+ visitor.EndArray(); \
+ }
+
+//// Elementary types
+
+void Reflect(Reader& visitor, uint8_t& value);
+void Reflect(Writer& visitor, uint8_t& value);
+
+void Reflect(Reader& visitor, short& value);
+void Reflect(Writer& visitor, short& value);
+
+void Reflect(Reader& visitor, unsigned short& value);
+void Reflect(Writer& visitor, unsigned short& value);
+
+void Reflect(Reader& visitor, int& value);
+void Reflect(Writer& visitor, int& value);
+
+void Reflect(Reader& visitor, unsigned& value);
+void Reflect(Writer& visitor, unsigned& value);
+
+void Reflect(Reader& visitor, long& value);
+void Reflect(Writer& visitor, long& value);
+
+void Reflect(Reader& visitor, unsigned long& value);
+void Reflect(Writer& visitor, unsigned long& value);
+
+void Reflect(Reader& visitor, long long& value);
+void Reflect(Writer& visitor, long long& value);
+
+void Reflect(Reader& visitor, unsigned long long& value);
+void Reflect(Writer& visitor, unsigned long long& value);
+
+void Reflect(Reader& visitor, double& value);
+void Reflect(Writer& visitor, double& value);
+
+void Reflect(Reader& visitor, bool& value);
+void Reflect(Writer& visitor, bool& value);
+
+void Reflect(Reader& visitor, std::string& value);
+void Reflect(Writer& visitor, std::string& value);
+
+void Reflect(Reader& visitor, JsonNull& value);
+void Reflect(Writer& visitor, JsonNull& value);
+
+void Reflect(Reader& visitor, SerializeFormat& value);
+void Reflect(Writer& visitor, SerializeFormat& value);
+
+//// Type constructors
+
+template <typename T>
+void Reflect(Reader& visitor, boost::optional<T>& value) {
+ if (visitor.IsNull()) {
+ visitor.GetNull();
+ return;
+ }
+ T real_value;
+ Reflect(visitor, real_value);
+ value = std::move(real_value);
+}
+template <typename T>
+void Reflect(Writer& visitor, boost::optional<T>& value) {
+ if (value)
+ Reflect(visitor, *value);
+ else
+ visitor.Null();
+}
+
+
+template <typename T>
+void ReflectMember(Writer& visitor, const char* name, boost::optional<T>& value) {
+ // For TypeScript optional property key?: value in the spec,
+ // We omit both key and value if value is std::nullopt (null) for JsonWriter
+ // to reduce output. But keep it for other serialization formats.
+ if (value || visitor.Format() != SerializeFormat::Json) {
+ visitor.Key(name);
+ Reflect(visitor, value);
+ }
+}
+
+
+
+template <typename T>
+void ReflectMember(Writer& visitor,
+ const char* name,
+ T& value,
+ optionals_mandatory_tag) {
+ visitor.Key(name);
+ Reflect(visitor, value);
+}
+template <typename T>
+void ReflectMember(Reader& visitor,
+ const char* name,
+ T& value,
+ optionals_mandatory_tag) {
+ Reflect(visitor, value);
+}
+
+template<class T >
+void Reflect(Reader& visitor, std::map<std::string, T>& value)
+{
+ visitor.IterMap([&](const char* name,Reader& entry) {
+ T entry_value;
+ Reflect(entry, entry_value);
+ value[name]=(std::move(entry_value));
+ });
+}
+template<class _Ty >
+void Reflect(Writer& visitor, std::map<std::string, _Ty>& value)
+{
+ REFLECT_MEMBER_START();
+ for (auto& it : value)
+ {
+ visitor.Key(it.first.c_str());
+ Reflect(visitor, it.second);
+ }
+ REFLECT_MEMBER_END();
+}
+
+// std::vector
+template <typename T>
+void Reflect(Reader& visitor, std::vector<T>& values) {
+ visitor.IterArray([&](Reader& entry) {
+ T entry_value;
+ Reflect(entry, entry_value);
+ values.push_back(std::move(entry_value));
+ });
+}
+
+
+template <typename T>
+void Reflect(Writer& visitor, std::vector<T>& values) {
+ visitor.StartArray(values.size());
+ for (auto& value : values)
+ Reflect(visitor, value);
+ visitor.EndArray();
+}
+
+// ReflectMember
+
+inline void DefaultReflectMemberStart(Writer& visitor) {
+ visitor.StartObject();
+}
+inline void DefaultReflectMemberStart(Reader& visitor) {}
+
+template <typename T>
+bool ReflectMemberStart(Reader& visitor, T& value) {
+ return false;
+}
+template <typename T>
+bool ReflectMemberStart(Writer& visitor, T& value) {
+ visitor.StartObject();
+ return true;
+}
+
+template <typename T>
+void ReflectMemberEnd(Reader& visitor, T& value) {}
+template <typename T>
+void ReflectMemberEnd(Writer& visitor, T& value) {
+ visitor.EndObject();
+}
+
+template <typename T>
+void ReflectMember(Reader& visitor, const char* name, T& value) {
+ visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); });
+}
+template <typename T>
+void ReflectMember(Writer& visitor, const char* name, T& value) {
+ visitor.Key(name);
+ Reflect(visitor, value);
+}
+
+template<class _Ty1, class _Ty2>
+void Reflect(Writer& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value)
+{
+ if (value.first)
+ {
+ Reflect(visitor, value.first);
+ }
+ else
+ {
+ Reflect(visitor, value.second);
+ }
+}
+template<class _Ty2>
+void Reflect(Reader& visitor, std::pair< boost::optional<bool>, boost::optional<_Ty2> >& value)
+{
+ if(visitor.IsBool())
+ {
+ Reflect(visitor, value.first);
+ return;
+ }
+
+ Reflect(visitor, value.second);
+}
+template<class _Ty2>
+void Reflect(Reader& visitor, std::pair< boost::optional<std::string>, boost::optional<_Ty2> >& value)
+{
+ if (visitor.IsString())
+ {
+ Reflect(visitor, value.first);
+ return;
+ }
+
+ Reflect(visitor, value.second);
+}
+
+
+template<class _Ty1, class _Ty2>
+void Reflect(Reader& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value)
+{
+ try
+ {
+ Reflect(visitor, value.second);
+ }
+ catch (...)
+ {
+ Reflect(visitor, value.first);
+ }
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/stream.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/stream.h
new file mode 100644
index 0000000000..549c361950
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/stream.h
@@ -0,0 +1,196 @@
+#pragma once
+#include <mutex>
+#include <string>
+namespace lsp
+{
+ class stream
+ {
+ public:
+ virtual ~stream() = default;
+ virtual bool fail() = 0;
+ virtual bool bad() = 0;
+ virtual bool eof() = 0;
+ virtual bool good() = 0;
+ virtual void clear() = 0;
+ virtual std::string what() = 0;
+ virtual bool need_to_clear_the_state()
+ {
+ return false;
+ }
+
+ bool operator!()
+ {
+ return bad();
+ }
+ };
+ class istream : public stream
+ {
+ public:
+ virtual int get() = 0;
+ virtual ~istream() = default;
+ virtual istream& read(char* str, std::streamsize count) = 0;
+ };
+ template <class T >
+ class base_istream : public istream
+ {
+ public:
+ explicit base_istream(T& _t) :_impl(_t)
+ {
+
+ }
+
+ int get() override
+ {
+ return _impl.get();
+ }
+ bool fail() override
+ {
+ return _impl.fail();
+ }
+ bool bad() override
+ {
+ return _impl.bad();
+ }
+ bool eof() override
+ {
+ return _impl.eof();
+ }
+ bool good() override
+ {
+ return _impl.good();
+ }
+ istream& read(char* str, std::streamsize count) override
+ {
+ _impl.read(str, count);
+ return *this;
+ }
+
+ void clear() override
+ {
+ _impl.clear();
+ }
+ T& _impl;
+ };
+ class ostream : public stream
+ {
+ public:
+ virtual ~ostream() = default;
+
+ virtual ostream& write(const std::string&) = 0;
+ virtual ostream& write(std::streamsize) = 0;
+ virtual ostream& flush() = 0;
+
+ };
+ template <class T >
+ class base_ostream : public ostream
+ {
+ public:
+ explicit base_ostream(T& _t) :_impl(_t)
+ {
+
+ }
+
+ bool fail() override
+ {
+ return _impl.fail();
+ }
+ bool good() override
+ {
+ return _impl.good();
+ }
+ bool bad() override
+ {
+ return _impl.bad();
+ }
+ bool eof() override
+ {
+ return _impl.eof();
+ }
+
+ ostream& write(const std::string& c) override
+ {
+ _impl << c;
+ return *this;
+ }
+
+ ostream& write(std::streamsize _s) override
+ {
+
+ _impl << std::to_string(_s);
+ return *this;
+ }
+
+ ostream& flush() override
+ {
+ _impl.flush();
+ return *this;
+ }
+
+ void clear() override
+ {
+ _impl.clear();
+ }
+ protected:
+ T& _impl;
+ };
+
+ template <class T >
+ class base_iostream : public istream, public ostream
+ {
+ public:
+ explicit base_iostream(T& _t) :_impl(_t)
+ {
+
+ }
+
+ int get() override
+ {
+ return _impl.get();
+ }
+ bool fail() override
+ {
+ return _impl.fail();
+ }
+ bool bad() override
+ {
+ return _impl.bad();
+ }
+ bool eof() override
+ {
+ return _impl.eof();
+ }
+ bool good() override
+ {
+ return _impl.good();
+ }
+ istream& read(char* str, std::streamsize count) override
+ {
+ _impl.read(str, count);
+ return *this;
+ }
+ ostream& write(const std::string& c) override
+ {
+ _impl << c;
+ return *this;
+ }
+
+ ostream& write(std::streamsize _s) override
+ {
+ _impl << std::to_string(_s);
+ return *this;
+ }
+
+ ostream& flush() override
+ {
+ _impl.flush();
+ return *this;
+ }
+
+ void clear() override
+ {
+ _impl.clear();
+ }
+ protected:
+ T& _impl;
+ };
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.cpp b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.cpp
new file mode 100644
index 0000000000..17e965eadf
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.cpp
@@ -0,0 +1,20 @@
+#include "threaded_queue.h"
+
+// static
+bool MultiQueueWaiter::HasState(
+ std::initializer_list<BaseThreadQueue*> queues) {
+ for (BaseThreadQueue* queue : queues) {
+ if (!queue->IsEmpty())
+ return true;
+ }
+ return false;
+}
+
+bool MultiQueueWaiter::ValidateWaiter(
+ std::initializer_list<BaseThreadQueue*> queues) {
+ for (BaseThreadQueue* queue : queues) {
+ if (queue->waiter.get() != this)
+ return false;
+ }
+ return true;
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.h
new file mode 100644
index 0000000000..cca9f9a486
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/threaded_queue.h
@@ -0,0 +1,249 @@
+#pragma once
+
+#include <boost/optional/optional.hpp>
+#include <algorithm>
+#include <atomic>
+#include <condition_variable>
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+
+struct MultiQueueWaiter;
+
+struct BaseThreadQueue {
+ virtual ~BaseThreadQueue() = default;
+
+ virtual bool IsEmpty() = 0;
+
+ std::shared_ptr<MultiQueueWaiter> waiter;
+};
+
+// std::lock accepts two or more arguments. We define an overload for one
+// argument.
+namespace std {
+template <typename Lockable>
+void lock(Lockable& l) {
+ l.lock();
+}
+} // namespace std
+
+template <typename... Queue>
+struct MultiQueueLock {
+ MultiQueueLock(Queue... lockable) : tuple_{lockable...} { lock(); }
+ ~MultiQueueLock() { unlock(); }
+ void lock() { lock_impl(typename std::index_sequence_for<Queue...>{}); }
+ void unlock() { unlock_impl(typename std::index_sequence_for<Queue...>{}); }
+
+ private:
+ template <size_t... Is>
+ void lock_impl(std::index_sequence<Is...>) {
+ std::lock(std::get<Is>(tuple_)->mutex...);
+ }
+
+ template <size_t... Is>
+ void unlock_impl(std::index_sequence<Is...>) {
+ (void)std::initializer_list<int>{
+ (std::get<Is>(tuple_)->mutex.unlock(), 0)...};
+ }
+
+ std::tuple<Queue...> tuple_;
+};
+
+struct MultiQueueWaiter {
+ static bool HasState(std::initializer_list<BaseThreadQueue*> queues);
+
+ bool ValidateWaiter(std::initializer_list<BaseThreadQueue*> queues);
+
+ template <typename... BaseThreadQueue>
+ bool Wait(std::atomic<bool>& quit, BaseThreadQueue... queues) {
+ MultiQueueLock<BaseThreadQueue...> l(queues...);
+ while (!quit.load(std::memory_order_relaxed)) {
+ if (HasState({ queues... }))
+ return false;
+ cv.wait(l);
+ }
+ return true;
+ }
+ template <typename... BaseThreadQueue>
+ void WaitUntil(std::chrono::steady_clock::time_point t,
+ BaseThreadQueue... queues) {
+ MultiQueueLock<BaseThreadQueue...> l(queues...);
+ if (!HasState({ queues... }))
+ cv.wait_until(l, t);
+ }
+ template <typename... BaseThreadQueue>
+ void Wait(BaseThreadQueue... queues) {
+ assert(ValidateWaiter({queues...}));
+
+ MultiQueueLock<BaseThreadQueue...> l(queues...);
+ while (!HasState({queues...}))
+ cv.wait(l);
+ }
+
+ std::condition_variable_any cv;
+};
+
+// A threadsafe-queue. http://stackoverflow.com/a/16075550
+template <class T>
+struct ThreadedQueue : public BaseThreadQueue {
+ public:
+ ThreadedQueue() : ThreadedQueue(std::make_shared<MultiQueueWaiter>()) {}
+
+ explicit ThreadedQueue(std::shared_ptr<MultiQueueWaiter> waiter)
+ : total_count_(0) {
+ this->waiter = waiter;
+ }
+
+ // Returns the number of elements in the queue. This is lock-free.
+ size_t Size() const { return total_count_; }
+
+ // Add an element to the queue.
+ void Enqueue(T&& t, bool priority) {
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+ if (priority)
+ priority_.push_back(std::move(t));
+ else
+ queue_.push_back(std::move(t));
+ ++total_count_;
+ }
+ waiter->cv.notify_one();
+ }
+
+ // Add a set of elements to the queue.
+ void EnqueueAll(std::vector<T>&& elements, bool priority) {
+ if (elements.empty())
+ return;
+
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+ total_count_ += elements.size();
+ for (T& element : elements) {
+ if (priority)
+ priority_.push_back(std::move(element));
+ else
+ queue_.push_back(std::move(element));
+ }
+ elements.clear();
+ }
+
+ waiter->cv.notify_all();
+ }
+
+ // Returns true if the queue is empty. This is lock-free.
+ bool IsEmpty() { return total_count_ == 0; }
+
+ // Get the first element from the queue. Blocks until one is available.
+ T Dequeue() {
+ std::unique_lock<std::mutex> lock(mutex);
+ waiter->cv.wait(lock,
+ [&]() { return !priority_.empty() || !queue_.empty(); });
+
+ auto execute = [&](std::deque<T>* q) {
+ auto val = std::move(q->front());
+ q->pop_front();
+ --total_count_;
+ return std::move(val);
+ };
+ if (!priority_.empty())
+ return execute(&priority_);
+ return execute(&queue_);
+ }
+
+ // Get the first element from the queue without blocking. Returns a null
+ // value if the queue is empty.
+ boost::optional<T> TryDequeue(bool priority) {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ auto pop = [&](std::deque<T>* q) {
+ auto val = std::move(q->front());
+ q->pop_front();
+ --total_count_;
+ return std::move(val);
+ };
+
+ auto get_result = [&](std::deque<T>* first,
+ std::deque<T>* second) -> boost::optional<T> {
+ if (!first->empty())
+ return pop(first);
+ if (!second->empty())
+ return pop(second);
+ return {};
+ };
+
+ if (priority)
+ return get_result(&priority_, &queue_);
+ return get_result(&queue_, &priority_);
+ }
+ // Return all elements in the queue.
+ std::vector<T> DequeueAll() {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ total_count_ = 0;
+
+ std::vector<T> result;
+ result.reserve(priority_.size() + queue_.size());
+ while (!priority_.empty()) {
+ result.emplace_back(std::move(priority_.front()));
+ priority_.pop_front();
+ }
+ while (!queue_.empty()) {
+ result.emplace_back(std::move(queue_.front()));
+ queue_.pop_front();
+ }
+
+ return result;
+ }
+ std::vector<T> TryDequeueSome(size_t num) {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ std::vector<T> result;
+ num = std::min(num, priority_.size() + queue_.size());
+ total_count_ -= num;
+ result.reserve(num);
+ while (num)
+ {
+ if(!priority_.empty()) {
+ result.emplace_back(std::move(priority_.front()));
+ priority_.pop_front();
+ }
+ else
+ {
+ break;
+ }
+ num -= 1;
+ }
+ while (num)
+ {
+ if (!queue_.empty()) {
+ result.emplace_back(std::move(queue_.front()));
+ queue_.pop_front();
+ }
+ else
+ {
+ break;
+ }
+ num -= 1;
+ }
+ return result;
+ }
+ template <typename Fn>
+ void Iterate(Fn fn) {
+ std::lock_guard<std::mutex> lock(mutex);
+ for (auto& entry : priority_)
+ fn(entry);
+ for (auto& entry : queue_)
+ fn(entry);
+ }
+
+ mutable std::mutex mutex;
+
+ private:
+ std::atomic<int> total_count_;
+ std::deque<T> priority_;
+ std::deque<T> queue_;
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/JsonRpc/traits.h b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/traits.h
new file mode 100644
index 0000000000..ce8905a840
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/JsonRpc/traits.h
@@ -0,0 +1,158 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+
+#include <tuple>
+#include <type_traits>
+
+namespace lsp {
+namespace traits {
+
+// NthTypeOf returns the `N`th type in `Types`
+template <int N, typename... Types>
+using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type;
+
+// `IsTypeOrDerived<BASE, T>::value` is true iff `T` is of type `BASE`, or
+// derives from `BASE`.
+template <typename BASE, typename T>
+using IsTypeOrDerived = std::integral_constant<
+ bool,
+ std::is_base_of<BASE, typename std::decay<T>::type>::value ||
+ std::is_same<BASE, typename std::decay<T>::type>::value>;
+
+// `EachIsTypeOrDerived<N, BASES, TYPES>::value` is true iff all of the types in
+// the std::tuple `TYPES` is of, or derives from the corresponding indexed type
+// in the std::tuple `BASES`.
+// `N` must be equal to the number of types in both the std::tuple `BASES` and
+// `TYPES`.
+template <int N, typename BASES, typename TYPES>
+struct EachIsTypeOrDerived {
+ using base = typename std::tuple_element<N - 1, BASES>::type;
+ using type = typename std::tuple_element<N - 1, TYPES>::type;
+ using last_matches = IsTypeOrDerived<base, type>;
+ using others_match = EachIsTypeOrDerived<N - 1, BASES, TYPES>;
+ static constexpr bool value = last_matches::value && others_match::value;
+};
+
+// EachIsTypeOrDerived specialization for N = 1
+template <typename BASES, typename TYPES>
+struct EachIsTypeOrDerived<1, BASES, TYPES> {
+ using base = typename std::tuple_element<0, BASES>::type;
+ using type = typename std::tuple_element<0, TYPES>::type;
+ static constexpr bool value = IsTypeOrDerived<base, type>::value;
+};
+
+// EachIsTypeOrDerived specialization for N = 0
+template <typename BASES, typename TYPES>
+struct EachIsTypeOrDerived<0, BASES, TYPES> {
+ static constexpr bool value = true;
+};
+
+// Signature describes the signature of a function.
+template <typename RETURN, typename... PARAMETERS>
+struct Signature {
+ // The return type of the function signature
+ using ret = RETURN;
+ // The parameters of the function signature held in a std::tuple
+ using parameters = std::tuple<PARAMETERS...>;
+ // The type of the Nth parameter of function signature
+ template <std::size_t N>
+ using parameter = NthTypeOf<N, PARAMETERS...>;
+ // The total number of parameters
+ static constexpr std::size_t parameter_count = sizeof...(PARAMETERS);
+};
+
+// SignatureOf is a traits helper that infers the signature of the function,
+// method, static method, lambda, or function-like object `F`.
+template <typename F>
+struct SignatureOf {
+ // The signature of the function-like object `F`
+ using type = typename SignatureOf<decltype(&F::operator())>::type;
+};
+
+// SignatureOf specialization for a regular function or static method.
+template <typename R, typename... ARGS>
+struct SignatureOf<R (*)(ARGS...)> {
+ // The signature of the function-like object `F`
+ using type = Signature<typename std::decay<R>::type,
+ typename std::decay<ARGS>::type...>;
+};
+
+// SignatureOf specialization for a non-static method.
+template <typename R, typename C, typename... ARGS>
+struct SignatureOf<R (C::*)(ARGS...)> {
+ // The signature of the function-like object `F`
+ using type = Signature<typename std::decay<R>::type,
+ typename std::decay<ARGS>::type...>;
+};
+
+// SignatureOf specialization for a non-static, const method.
+template <typename R, typename C, typename... ARGS>
+struct SignatureOf<R (C::*)(ARGS...) const> {
+ // The signature of the function-like object `F`
+ using type = Signature<typename std::decay<R>::type,
+ typename std::decay<ARGS>::type...>;
+};
+
+// SignatureOfT is an alias to `typename SignatureOf<F>::type`.
+template <typename F>
+using SignatureOfT = typename SignatureOf<F>::type;
+
+// ParameterType is an alias to `typename SignatureOf<F>::type::parameter<N>`.
+template <typename F, std::size_t N>
+using ParameterType = typename SignatureOfT<F>::template parameter<N>;
+
+// `HasSignature<F, S>::value` is true iff the function-like `F` has a matching
+// signature to the function-like `S`.
+template <typename F, typename S>
+using HasSignature = std::integral_constant<
+ bool,
+ std::is_same<SignatureOfT<F>, SignatureOfT<S>>::value>;
+
+// `Min<A, B>::value` resolves to the smaller value of A and B.
+template <std::size_t A, std::size_t B>
+using Min = std::integral_constant<std::size_t, (A < B ? A : B)>;
+
+// `CompatibleWith<F, S>::value` is true iff the function-like `F`
+// can be called with the argument types of the function-like `S`. Return type
+// of the two functions are not considered.
+template <typename F, typename S>
+using CompatibleWith = std::integral_constant<
+ bool,
+ (SignatureOfT<S>::parameter_count == SignatureOfT<F>::parameter_count) &&
+ EachIsTypeOrDerived<Min<SignatureOfT<S>::parameter_count,
+ SignatureOfT<F>::parameter_count>::value,
+ typename SignatureOfT<S>::parameters,
+ typename SignatureOfT<F>::parameters>::value>;
+
+// If `CONDITION` is true then EnableIf resolves to type T, otherwise an
+// invalid type.
+template <bool CONDITION, typename T = void>
+using EnableIf = typename std::enable_if<CONDITION, T>::type;
+
+// If `BASE` is a base of `T` then EnableIfIsType resolves to type `TRUE`,
+// otherwise an invalid type.
+template <typename BASE, typename T, typename TRUE_ = void>
+using EnableIfIsType = EnableIf<IsTypeOrDerived<BASE, T>::value, TRUE_>;
+
+// If the function-like `F` has a matching signature to the function-like `S`
+// then EnableIfHasSignature resolves to type `TRUE`, otherwise an invalid type.
+template <typename F, typename S, typename TRUE_ = void>
+using EnableIfHasSignature = EnableIf<HasSignature<F, S>::value, TRUE_>;
+
+} // namespace traits
+} // namespace lsp
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/AbsolutePath.h b/graphics/asymptote/LspCpp/LibLsp/lsp/AbsolutePath.h
new file mode 100644
index 0000000000..ef1ee43860
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/AbsolutePath.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <LibLsp/JsonRpc/serializer.h>
+#include <string>
+
+struct AbsolutePath {
+ static AbsolutePath BuildDoNotUse(const std::string& path);
+
+ // Try not to use this.
+ AbsolutePath();
+
+ // Provide implicit conversions to std::string for the time being.
+ AbsolutePath(const std::string& path, bool validate = true);
+ operator std::string() const;
+
+ bool operator==(const AbsolutePath& rhs) const;
+ bool operator!=(const AbsolutePath& rhs) const;
+ bool operator<(const AbsolutePath& rhs) const;
+ bool operator>(const AbsolutePath& rhs) const;
+ std::string path;
+ bool qualify = true;
+};
+
+
+void Reflect(Reader& visitor, AbsolutePath& value);
+void Reflect(Writer& visitor, AbsolutePath& value);
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ClientPreferences.h b/graphics/asymptote/LspCpp/LibLsp/lsp/ClientPreferences.h
new file mode 100644
index 0000000000..7adf557f83
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ClientPreferences.h
@@ -0,0 +1,306 @@
+#pragma once
+#include <LibLsp/lsp/general/lsClientCapabilities.h>
+#include <LibLsp/lsp/utils.h>
+#include <memory>
+#include <vector>
+#include <string>
+
+class ClientPreferences
+{
+public:
+
+ std::shared_ptr<lsWorkspaceClientCapabilites> workspace;
+ lsTextDocumentClientCapabilities textDocument ;
+
+ ClientPreferences(const lsClientCapabilities& capabilities)
+ {
+ v3supported = capabilities.textDocument.has_value();
+ if (v3supported)
+ textDocument = capabilities.textDocument.value();
+ if(capabilities.workspace)
+ {
+ workspace = std::make_shared<lsWorkspaceClientCapabilites>(capabilities.workspace.value());
+ }
+ }
+
+ bool v3supported=false;
+
+ bool isSignatureHelpSupported() {
+
+ return v3supported && (textDocument.signatureHelp);
+ }
+ bool isWorkspaceDidChangeConfigurationSupported() const
+ {
+ return workspace && isDynamicRegistrationSupported(workspace->didChangeConfiguration);
+ }
+ bool isWorkspaceFoldersSupported() {
+ return workspace != nullptr && isTrue(workspace->workspaceFolders);
+ }
+
+ bool isCompletionDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.completion);
+ }
+
+ bool isCompletionSnippetsSupported() {
+ //@formatter:off
+ if(!v3supported || !textDocument.completion)
+ {
+ return false;
+ }
+ const auto& completion = textDocument.completion.value();
+ if(completion.completionItem)
+ {
+ return isTrue(completion.completionItem.value().snippetSupport);
+ }
+ return false;
+ }
+
+ bool isV3Supported() {
+ return v3supported;
+ }
+
+ bool isFormattingDynamicRegistrationSupported() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.formatting);
+ }
+
+ bool isRangeFormattingDynamicRegistrationSupported() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.rangeFormatting);
+ }
+
+ bool isOnTypeFormattingDynamicRegistrationSupported() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.onTypeFormatting);
+ }
+
+ bool isCodeLensDynamicRegistrationSupported() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.codeLens);
+ }
+
+ bool isSignatureHelpDynamicRegistrationSupported() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.signatureHelp);
+ }
+ template<typename T>
+ static bool isDynamicRegistrationSupported(boost::optional<T>& capability)
+ {
+ if(capability)
+ return (capability.value().dynamicRegistration.value());
+ return false;
+ }
+
+ bool isTrue(const boost::optional<bool>& value)
+ {
+ return value.get_value_or(false);
+ }
+
+ bool isRenameDynamicRegistrationSupported() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.rename);
+ }
+
+ bool isExecuteCommandDynamicRegistrationSupported() {
+ return v3supported && workspace != nullptr && isDynamicRegistrationSupported(workspace->executeCommand);
+ }
+
+ bool isWorkspaceSymbolDynamicRegistered() {
+ return v3supported && workspace != nullptr && isDynamicRegistrationSupported(workspace->symbol);
+ }
+
+ bool isWorkspaceChangeWatchedFilesDynamicRegistered() {
+ return v3supported && workspace != nullptr && isDynamicRegistrationSupported(workspace->didChangeWatchedFiles);
+ }
+
+ bool isDocumentSymbolDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.documentSymbol);
+ }
+
+ bool isCodeActionDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.codeAction);
+ }
+
+ bool isDefinitionDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.definition);
+ }
+
+ bool isTypeDefinitionDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.typeDefinition);
+ }
+
+ bool isHoverDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.hover);
+ }
+
+ bool isReferencesDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.references);
+ }
+
+ bool isDocumentHighlightDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.documentHighlight);
+ }
+
+ bool isFoldgingRangeDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.foldingRange);
+ }
+
+ bool isImplementationDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.implementation);
+ }
+
+ bool isSelectionRangeDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.selectionRange);
+ }
+
+ bool isWillSaveRegistered() {
+ return v3supported && isTrue(textDocument.synchronization.willSave);
+ }
+
+ bool isWillSaveWaitUntilRegistered() {
+ return v3supported && isTrue(textDocument.synchronization.willSaveWaitUntil);
+ }
+
+ bool isWorkspaceApplyEditSupported() {
+ return workspace != nullptr && isTrue(workspace->applyEdit);
+ }
+
+ bool isSupportsCompletionDocumentationMarkdown() {
+
+ if (!v3supported || !textDocument.completion)
+ {
+ return false;
+ }
+ const auto& completion = textDocument.completion.value();
+ if (completion.completionItem)
+ {
+ auto& documentationFormat = completion.completionItem.value().documentationFormat;
+ if(documentationFormat)
+ {
+ auto& data = documentationFormat.value();
+ for(auto& it : data)
+ {
+ if(it == "markdown")
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+
+ }
+
+
+ bool isWorkspaceEditResourceChangesSupported() {
+ if(!workspace) return false;
+
+ if(workspace->workspaceEdit)
+ {
+ return isTrue(workspace->workspaceEdit.value().resourceChanges);
+ }
+ return false;
+ }
+ static bool contains(const std::vector<std::string>& v, const std::string& target)
+ {
+ for(auto& it : v)
+ {
+ if(it == target) return true;
+ }
+ return false;
+ }
+ bool isResourceOperationSupported() const
+ {
+ if (!workspace) return false;
+ if (!workspace->workspaceEdit)
+ {
+ return false;
+ }
+ auto& it = (workspace->workspaceEdit.value());
+ if(!it.resourceOperations) return false;
+ const auto& resourceOperations = it.resourceOperations.value();
+ return contains(resourceOperations, "create") && contains(resourceOperations, "rename") && contains(resourceOperations, "delete");
+
+ }
+
+ /**
+ * {@code true} if the client has explicitly set the
+ * {@code textDocument.documentSymbol.hierarchicalDocumentSymbolSupport} to
+ * {@code true} when initializing the LS. Otherwise, {@code false}.
+ */
+ bool isHierarchicalDocumentSymbolSupported() {
+ if(!v3supported || !textDocument.documentSymbol) return false;
+ return isTrue(textDocument.documentSymbol.value().hierarchicalDocumentSymbolSupport);
+
+ }
+
+ bool isSemanticHighlightingSupported() {
+ //@formatter:off
+ if (!v3supported || !textDocument.semanticHighlightingCapabilities) return false;
+ return isTrue(textDocument.semanticHighlightingCapabilities.value().semanticHighlighting);
+ //@formatter:on
+ }
+
+ /**
+ * {@code true} if the client has explicitly set the
+ * {@code textDocument.codeAction.codeActionLiteralSupport.codeActionKind.valueSet}
+ * value. Otherwise, {@code false}.
+ */
+ bool isSupportedCodeActionKind(const std::string& kind) {
+ if (!v3supported || !textDocument.codeAction) return false;
+ //@formatter:off
+ const auto& codeAction = textDocument.codeAction.value();
+ if(codeAction.codeActionLiteralSupport)
+ {
+ const auto& codeActionKind = codeAction.codeActionLiteralSupport.value().codeActionKind;
+ if(codeActionKind)
+ {
+ const auto& valueSet = codeActionKind.value().valueSet;
+ if(valueSet)
+ {
+ for(auto& k : valueSet.value())
+ {
+ if(lsp::StartsWith(kind,k))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+
+ //@formatter:on
+ }
+
+ /**
+ * {@code true} if the client has explicitly set the
+ * {@code textDocument.publishDiagnostics.tagSupport} to
+ * {@code true} when initializing the LS. Otherwise, {@code false}.
+ */
+ bool isDiagnosticTagSupported() {
+ if (!v3supported || !textDocument.publishDiagnostics) return false;
+ const auto& publishDiagnostics = textDocument.publishDiagnostics.value();
+ if(publishDiagnostics.tagSupport)
+ {
+ isTagSupported(publishDiagnostics.tagSupport);
+ }
+ return false;
+ }
+
+ bool isTagSupported(const boost::optional < std::pair<boost::optional<bool>,
+ boost::optional<DiagnosticsTagSupport> > >& tagSupport) {
+ if(tagSupport)
+ {
+ auto &v = tagSupport.value();
+ if (v.first)
+ {
+ return v.first.value();
+ }
+ if (v.second) {
+ return !v.second.value().valueSet.empty();
+ }
+ }
+ return false;
+ }
+
+ bool isCallHierarchyDynamicRegistered() {
+ return v3supported && isDynamicRegistrationSupported(textDocument.callHierarchy);
+ }
+
+};
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/CodeActionParams.h b/graphics/asymptote/LspCpp/LibLsp/lsp/CodeActionParams.h
new file mode 100644
index 0000000000..a1e3f1dcc1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/CodeActionParams.h
@@ -0,0 +1,114 @@
+#pragma once
+#include "LibLsp/lsp/method_type.h"
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsp_diagnostic.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+#include "LibLsp/lsp/lsCodeAction.h"
+namespace JDT
+{
+ namespace CodeActionKind {
+
+
+ /**
+ * Base kind for quickfix actions: 'quickfix'
+ */
+ extern const char* QuickFix;
+
+ /**
+ * Base kind for refactoring actions: 'refactor'
+ */
+ extern const char* Refactor;
+
+ /**
+ * Base kind for refactoring extraction actions: 'refactor.extract'
+ *
+ * Example extract actions:
+ *
+ * - Extract method - Extract function - Extract variable - Extract interface
+ * from class - ...
+ */
+ extern const char* RefactorExtract;
+
+ /**
+ * Base kind for refactoring inline actions: 'refactor.inline'
+ *
+ * Example inline actions:
+ *
+ * - Inline function - Inline variable - Inline constant - ...
+ */
+ extern const char* RefactorInline;
+
+ /**
+ * Base kind for refactoring rewrite actions: 'refactor.rewrite'
+ *
+ * Example rewrite actions:
+ *
+ * - Convert JavaScript function to class - Add or remove parameter -
+ * Encapsulate field - Make method static - Move method to base class - ...
+ */
+ extern const char* RefactorRewrite;
+
+ /**
+ * Base kind for source actions: `source`
+ *
+ * Source code actions apply to the entire file.
+ */
+ extern const char* Source ;
+
+ /**
+ * Base kind for an organize imports source action: `source.organizeImports`
+ */
+ extern const char* SourceOrganizeImports;
+
+ extern const char* COMMAND_ID_APPLY_EDIT;
+ };
+
+
+}
+struct lsCodeActionContext {
+ // An array of diagnostics.
+ std::vector<lsDiagnostic> diagnostics;
+ /**
+ * Requested kind of actions to return.
+ *
+ * Actions not of this kind are filtered out by the client before being shown. So servers
+ * can omit computing them.
+ *
+ * See {@link CodeActionKind} for allowed values.
+ */
+ boost::optional<std::vector<std::string>> only;
+
+ MAKE_SWAP_METHOD(lsCodeActionContext,
+ diagnostics, only);
+};
+MAKE_REFLECT_STRUCT(lsCodeActionContext,
+ diagnostics, only);
+
+
+// Params for the CodeActionRequest
+struct lsCodeActionParams {
+ // The document in which the command was invoked.
+ lsTextDocumentIdentifier textDocument;
+ // The range for which the command was invoked.
+ lsRange range;
+ // Context carrying additional information.
+ lsCodeActionContext context;
+
+ MAKE_SWAP_METHOD(lsCodeActionParams,
+ textDocument,
+ range,
+ context);
+};
+MAKE_REFLECT_STRUCT(lsCodeActionParams,
+ textDocument,
+ range,
+ context);
+
+
+
+
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/Directory.h b/graphics/asymptote/LspCpp/LibLsp/lsp/Directory.h
new file mode 100644
index 0000000000..93f2c0807d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/Directory.h
@@ -0,0 +1,13 @@
+#pragma once
+#include <string>
+
+struct AbsolutePath;
+
+struct Directory {
+ explicit Directory(const AbsolutePath& path);
+
+ bool operator==(const Directory& rhs) const;
+ bool operator!=(const Directory& rhs) const;
+
+ std::string path;
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ExecuteCommandParams.h b/graphics/asymptote/LspCpp/LibLsp/lsp/ExecuteCommandParams.h
new file mode 100644
index 0000000000..c06eed4b1c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ExecuteCommandParams.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "lsAny.h"
+struct ExecuteCommandParams {
+ /**
+ * The identifier of the actual command handler.
+ */
+
+ std::string command;
+
+ /**
+ * Arguments that the command should be invoked with.
+ * The arguments are typically specified when a command is returned from the server to the client.
+ * Example requests that return a command are textDocument/codeAction or textDocument/codeLens.
+ */
+ boost::optional<std::vector<lsp::Any>> arguments;
+
+ MAKE_SWAP_METHOD(ExecuteCommandParams, command, arguments);
+};
+MAKE_REFLECT_STRUCT(ExecuteCommandParams,command,arguments)
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/IProgressMonitor.h b/graphics/asymptote/LspCpp/LibLsp/lsp/IProgressMonitor.h
new file mode 100644
index 0000000000..bf1337e44f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/IProgressMonitor.h
@@ -0,0 +1,145 @@
+#pragma once
+
+
+#include <string>
+namespace lsp {
+/**
+ * The <code>IProgressMonitor</code> interface is implemented
+ * by objects that monitor the progress of an activity; the methods
+ * in this interface are invoked by code that performs the activity.
+ * <p>
+ * All activity is broken down into a linear sequence of tasks against
+ * which progress is reported. When a task begins, a <code>beginTask(const wstring&, int)
+ * </code> notification is reported, followed by any number and mixture of
+ * progress reports (<code>worked()</code>) and subtask notifications
+ * (<code>subTask(const wstring&)</code>). When the task is eventually completed, a
+ * <code>done()</code> notification is reported. After the <code>done()</code>
+ * notification, the progress monitor cannot be reused; i.e., <code>
+ * beginTask(const wstring&, int)</code> cannot be called again after the call to
+ * <code>done()</code>.
+ * </p>
+ * <p>
+ * A request to cancel an operation can be signaled using the
+ * <code>setCanceled</code> method. Operations taking a progress
+ * monitor are expected to poll the monitor (using <code>isCanceled</code>)
+ * periodically and abort at their earliest convenience. Operation can however
+ * choose to ignore cancelation requests.
+ * </p>
+ * <p>
+ * Since notification is synchronous with the activity itself, the listener should
+ * provide a fast and robust implementation. If the handling of notifications would
+ * involve blocking operations, or operations which might throw uncaught exceptions,
+ * the notifications should be queued, and the actual processing deferred (or perhaps
+ * delegated to a separate thread).
+ * </p>
+ * <p>
+ * Clients may implement this interface.
+ * </p>
+ */
+ class IProgressMonitor {
+ public:
+ virtual ~IProgressMonitor()
+ {
+ }
+
+ /** Constant indicating an unknown amount of work.
+ */
+
+ const static int UNKNOWN = -1;
+
+ /**
+ * Notifies that the main task is beginning. This must only be called once
+ * on a given progress monitor instance.
+ *
+ * @param name the name (or description) of the main task
+ * @param totalWork the total number of work units into which
+ * the main task is been subdivided. If the value is <code>UNKNOWN</code>
+ * the implemenation is free to indicate progress in a way which
+ * doesn't require the total number of work units in advance.
+ */
+ virtual void beginTask(void* , int totalWork)
+ {
+
+ };
+ /**
+ * Notifies that the work is done; that is, either the main task is completed
+ * or the user canceled it. This method may be called more than once
+ * (implementations should be prepared to handle this case).
+ */
+
+ virtual void endTask(void*, int totalWork)
+ {
+
+ }
+
+ virtual void done(void*) = 0;
+
+ /**
+ * Internal method to handle scaling correctly. This method
+ * must not be called by a client. Clients should
+ * always use the method </code>worked(int)</code>.
+ */
+ virtual void internalWorked(double work)
+ {
+
+ }
+ /**
+ * Returns whether cancelation of current operation has been requested.
+ * Long-running operations should poll to see if cancelation
+ * has been requested.
+ *
+ * @return <code>true</code> if cancellation has been requested,
+ * and <code>false</code> otherwise
+ * @see #setCanceled
+ */
+ virtual bool isCanceled() = 0;
+ /**
+ * Sets the cancel state to the given value.
+ *
+ * @param value <code>true</code> indicates that cancelation has
+ * been requested (but not necessarily acknowledged);
+ * <code>false</code> clears this flag
+ *
+ * @see #isCanceled
+ */
+ virtual void setCanceled(bool value) = 0;
+ /**
+ * Sets the task name to the given value. This method is used to
+ * restore the task label after a nested operation was executed.
+ * Normally there is no need for clients to call this method.
+ *
+ * @param name the name (or description) of the main task
+ * @see #beginTask(java.lang.const wstring&, int)
+ */
+ virtual void setTaskName(void*)
+ {
+
+ };
+ /**
+ * Notifies that a subtask of the main task is beginning.
+ * Subtasks are optional; the main task might not have subtasks.
+ *
+ * @param name the name (or description) of the subtask
+ */
+ virtual void subTask(void* )
+ {
+
+ }
+ /**
+ * Notifies that a given number of work unit of the main task
+ * has been completed. Note that this amount represents an
+ * installment, as opposed to a cumulative amount of work done
+ * to date.
+ *
+ * @param work the number of work units just completed
+ */
+ virtual void worked(int work)
+ {
+
+ };
+
+ virtual void catch_exception(void*) = 0;
+ };
+}
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.cpp
new file mode 100644
index 0000000000..f65f8ad3ce
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.cpp
@@ -0,0 +1,942 @@
+//===--- Markup.cpp -----------------------------------------*- C++-*------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://lsp.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "Markup.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <vector>
+#include <boost/algorithm/string.hpp>
+
+namespace lsp {
+
+ /// hexdigit - Return the hexadecimal character for the
+ /// given number \p X (which should be less than 16).
+ inline char hexdigit(unsigned X, bool LowerCase = false) {
+ const char HexChar = LowerCase ? 'a' : 'A';
+ return X < 10 ? '0' + X : HexChar + X - 10;
+ }
+
+ /// Given an array of c-style strings terminated by a null pointer, construct
+ /// a vector of StringRefs representing the same strings without the terminating
+ /// null string.
+ inline std::vector< std::string_ref> toStringRefArray(const char* const* Strings) {
+ std::vector< std::string_ref> Result;
+ while (*Strings)
+ Result.push_back(*Strings++);
+ return Result;
+ }
+
+ /// Construct a string ref from a boolean.
+ inline std::string_ref toStringRef(bool B) { return std::string_ref(B ? "true" : "false"); }
+
+ /// Construct a string ref from an array ref of unsigned chars.
+ inline std::string_ref toStringRef(const std::vector<uint8_t>& Input) {
+ return std::string_ref(Input.begin(), Input.end());
+ }
+
+ /// Construct a string ref from an array ref of unsigned chars.
+ inline std::vector<uint8_t> arrayRefFromStringRef(const std::string_ref& Input) {
+ return { Input.begin(), Input.end() };
+ }
+
+ /// Interpret the given character \p C as a hexadecimal digit and return its
+ /// value.
+ ///
+ /// If \p C is not a valid hex digit, -1U is returned.
+ inline unsigned hexDigitValue(char C) {
+ struct HexTable {
+ unsigned LUT[255] = {};
+ constexpr HexTable() {
+ // Default initialize everything to invalid.
+ for (int i = 0; i < 255; ++i)
+ LUT[i] = ~0U;
+ // Initialize `0`-`9`.
+ for (int i = 0; i < 10; ++i)
+ LUT['0' + i] = i;
+ // Initialize `A`-`F` and `a`-`f`.
+ for (int i = 0; i < 6; ++i)
+ LUT['A' + i] = LUT['a' + i] = 10 + i;
+ }
+ };
+ constexpr HexTable Table;
+ return Table.LUT[static_cast<unsigned char>(C)];
+ }
+
+ /// Checks if character \p C is one of the 10 decimal digits.
+ inline bool isDigit(char C) { return C >= '0' && C <= '9'; }
+
+ /// Checks if character \p C is a hexadecimal numeric character.
+ inline bool isHexDigit(char C) { return hexDigitValue(C) != ~0U; }
+
+ /// Checks if character \p C is a valid letter as classified by "C" locale.
+ inline bool isAlpha(char C) {
+ return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z');
+ }
+
+ /// Checks whether character \p C is either a decimal digit or an uppercase or
+ /// lowercase letter as classified by "C" locale.
+ inline bool isAlnum(char C) { return isAlpha(C) || isDigit(C); }
+
+ /// Checks whether character \p C is valid ASCII (high bit is zero).
+ inline bool isASCII(char C) { return static_cast<unsigned char>(C) <= 127; }
+
+ /// Checks whether all characters in S are ASCII.
+ inline bool isASCII(std::string_ref S) {
+ for (char C : S)
+ {
+ if(!isASCII(C))return true;
+ }
+ return true;
+ }
+
+ /// Checks whether character \p C is printable.
+ ///
+ /// Locale-independent version of the C standard library isprint whose results
+ /// may differ on different platforms.
+ inline bool isPrint(char C) {
+ unsigned char UC = static_cast<unsigned char>(C);
+ return (0x20 <= UC) && (UC <= 0x7E);
+ }
+
+ /// Checks whether character \p C is whitespace in the "C" locale.
+ ///
+ /// Locale-independent version of the C standard library isspace.
+ inline bool isSpace(char C) {
+ return C == ' ' || C == '\f' || C == '\n' || C == '\r' || C == '\t' ||
+ C == '\v';
+ }
+
+ /// Returns the corresponding lowercase character if \p x is uppercase.
+ inline char toLower(char x) {
+ if (x >= 'A' && x <= 'Z')
+ return x - 'A' + 'a';
+ return x;
+ }
+
+ /// Returns the corresponding uppercase character if \p x is lowercase.
+ inline char toUpper(char x) {
+ if (x >= 'a' && x <= 'z')
+ return x - 'a' + 'A';
+ return x;
+ }
+
+ inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
+ char Buffer[17];
+ char* BufPtr = std::end(Buffer);
+
+ if (X == 0) *--BufPtr = '0';
+
+ while (X) {
+ unsigned char Mod = static_cast<unsigned char>(X) & 15;
+ *--BufPtr = hexdigit(Mod, LowerCase);
+ X >>= 4;
+ }
+
+ return std::string(BufPtr, std::end(Buffer));
+ }
+
+ /// Convert buffer \p Input to its hexadecimal representation.
+ /// The returned string is double the size of \p Input.
+ inline std::string toHex( std::string_ref Input, bool LowerCase = false) {
+ static const char* const LUT = "0123456789ABCDEF";
+ const uint8_t Offset = LowerCase ? 32 : 0;
+ size_t Length = Input.size();
+
+ std::string Output;
+ Output.reserve(2 * Length);
+ for (size_t i = 0; i < Length; ++i) {
+ const unsigned char c = Input[i];
+ Output.push_back(LUT[c >> 4] | Offset);
+ Output.push_back(LUT[c & 15] | Offset);
+ }
+ return Output;
+ }
+
+ inline std::string toHex(std::vector<uint8_t> Input, bool LowerCase = false) {
+ return toHex(toStringRef(Input), LowerCase);
+ }
+
+ /// Store the binary representation of the two provided values, \p MSB and
+ /// \p LSB, that make up the nibbles of a hexadecimal digit. If \p MSB or \p LSB
+ /// do not correspond to proper nibbles of a hexadecimal digit, this method
+ /// returns false. Otherwise, returns true.
+ inline bool tryGetHexFromNibbles(char MSB, char LSB, uint8_t& Hex) {
+ unsigned U1 = hexDigitValue(MSB);
+ unsigned U2 = hexDigitValue(LSB);
+ if (U1 == ~0U || U2 == ~0U)
+ return false;
+
+ Hex = static_cast<uint8_t>((U1 << 4) | U2);
+ return true;
+ }
+
+ /// Return the binary representation of the two provided values, \p MSB and
+ /// \p LSB, that make up the nibbles of a hexadecimal digit.
+ inline uint8_t hexFromNibbles(char MSB, char LSB) {
+ uint8_t Hex = 0;
+ bool GotHex = tryGetHexFromNibbles(MSB, LSB, Hex);
+ (void)GotHex;
+ assert(GotHex && "MSB and/or LSB do not correspond to hex digits");
+ return Hex;
+ }
+
+ /// Convert hexadecimal string \p Input to its binary representation and store
+ /// the result in \p Output. Returns true if the binary representation could be
+ /// converted from the hexadecimal string. Returns false if \p Input contains
+ /// non-hexadecimal digits. The output string is half the size of \p Input.
+ inline bool tryGetFromHex( std::string_ref Input, std::string& Output) {
+ if (Input.empty())
+ return true;
+
+ Output.reserve((Input.size() + 1) / 2);
+ if (Input.size() % 2 == 1) {
+ uint8_t Hex = 0;
+ if (!tryGetHexFromNibbles('0', Input.front(), Hex))
+ return false;
+
+ Output.push_back(Hex);
+ Input = Input.drop_front();
+ }
+
+ assert(Input.size() % 2 == 0);
+ while (!Input.empty()) {
+ uint8_t Hex = 0;
+ if (!tryGetHexFromNibbles(Input[0], Input[1], Hex))
+ return false;
+
+ Output.push_back(Hex);
+ Input = Input.drop_front(2);
+ }
+ return true;
+ }
+
+ /// Convert hexadecimal string \p Input to its binary representation.
+ /// The return string is half the size of \p Input.
+ inline std::string fromHex( std::string_ref Input) {
+ std::string Hex;
+ bool GotHex = tryGetFromHex(Input, Hex);
+ (void)GotHex;
+ assert(GotHex && "Input contains non hex digits");
+ return Hex;
+ }
+
+
+
+ inline std::string utostr(uint64_t X, bool isNeg = false) {
+ char Buffer[21];
+ char* BufPtr = std::end(Buffer);
+
+ if (X == 0) *--BufPtr = '0'; // Handle special case...
+
+ while (X) {
+ *--BufPtr = '0' + char(X % 10);
+ X /= 10;
+ }
+
+ if (isNeg) *--BufPtr = '-'; // Add negative sign...
+ return std::string(BufPtr, std::end(Buffer));
+ }
+
+ inline std::string itostr(int64_t X) {
+ if (X < 0)
+ return utostr(static_cast<uint64_t>(1) + ~static_cast<uint64_t>(X), true);
+ else
+ return utostr(static_cast<uint64_t>(X));
+ }
+
+ /// StrInStrNoCase - Portable version of strcasestr. Locates the first
+ /// occurrence of string 's1' in string 's2', ignoring case. Returns
+ /// the offset of s2 in s1 or npos if s2 cannot be found.
+ std::string_ref::size_type StrInStrNoCase( std::string_ref s1, std::string_ref s2);
+
+ /// getToken - This function extracts one token from source, ignoring any
+ /// leading characters that appear in the Delimiters string, and ending the
+ /// token at any of the characters that appear in the Delimiters string. If
+ /// there are no tokens in the source string, an empty string is returned.
+ /// The function returns a pair containing the extracted token and the
+ /// remaining tail string.
+ std::pair< std::string_ref, std::string_ref> getToken( std::string_ref Source,
+ std::string_ref Delimiters = " \t\n\v\f\r");
+
+
+
+ /// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th).
+ inline std::string_ref getOrdinalSuffix(unsigned Val) {
+ // It is critically important that we do this perfectly for
+ // user-written sequences with over 100 elements.
+ switch (Val % 100) {
+ case 11:
+ case 12:
+ case 13:
+ return "th";
+ default:
+ switch (Val % 10) {
+ case 1: return "st";
+ case 2: return "nd";
+ case 3: return "rd";
+ default: return "th";
+ }
+ }
+ }
+
+ namespace detail {
+
+ template <typename IteratorT>
+ inline std::string join_impl(IteratorT Begin, IteratorT End,
+ std::string_ref Separator, std::input_iterator_tag) {
+ std::string S;
+ if (Begin == End)
+ return S;
+
+ S += (*Begin);
+ while (++Begin != End) {
+ S += Separator;
+ S += (*Begin);
+ }
+ return S;
+ }
+
+ template <typename IteratorT>
+ inline std::string join_impl(IteratorT Begin, IteratorT End,
+ std::string_ref Separator, std::forward_iterator_tag) {
+ std::string S;
+ if (Begin == End)
+ return S;
+
+ size_t Len = (std::distance(Begin, End) - 1) * Separator.size();
+ for (IteratorT I = Begin; I != End; ++I)
+ Len += (*I).size();
+ S.reserve(Len);
+ size_t PrevCapacity = S.capacity();
+ (void)PrevCapacity;
+ S += (*Begin);
+ while (++Begin != End) {
+ S += Separator;
+ S += (*Begin);
+ }
+ assert(PrevCapacity == S.capacity() && "String grew during building");
+ return S;
+ }
+
+ template <typename Sep>
+ inline void join_items_impl(std::string& Result, Sep Separator) {}
+
+ template <typename Sep, typename Arg>
+ inline void join_items_impl(std::string& Result, Sep Separator,
+ const Arg& Item) {
+ Result += Item;
+ }
+
+ template <typename Sep, typename Arg1, typename... Args>
+ inline void join_items_impl(std::string& Result, Sep Separator, const Arg1& A1,
+ Args &&... Items) {
+ Result += A1;
+ Result += Separator;
+ join_items_impl(Result, Separator, std::forward<Args>(Items)...);
+ }
+
+ inline size_t join_one_item_size(char) { return 1; }
+ inline size_t join_one_item_size(const char* S) { return S ? ::strlen(S) : 0; }
+
+ template <typename T> inline size_t join_one_item_size(const T& Str) {
+ return Str.size();
+ }
+
+ inline size_t join_items_size() { return 0; }
+
+ template <typename A1> inline size_t join_items_size(const A1& A) {
+ return join_one_item_size(A);
+ }
+ template <typename A1, typename... Args>
+ inline size_t join_items_size(const A1& A, Args &&... Items) {
+ return join_one_item_size(A) + join_items_size(std::forward<Args>(Items)...);
+ }
+
+ } // end namespace detail
+
+ /// Joins the strings in the range [Begin, End), adding Separator between
+ /// the elements.
+ template <typename IteratorT>
+ inline std::string join(IteratorT Begin, IteratorT End, std::string_ref Separator) {
+ using tag = typename std::iterator_traits<IteratorT>::iterator_category;
+ return detail::join_impl(Begin, End, Separator, tag());
+ }
+
+ /// Joins the strings in the range [R.begin(), R.end()), adding Separator
+ /// between the elements.
+ template <typename Range>
+ inline std::string join(Range&& R, std::string_ref Separator) {
+ return join(R.begin(), R.end(), Separator);
+ }
+
+ /// Joins the strings in the parameter pack \p Items, adding \p Separator
+ /// between the elements. All arguments must be implicitly convertible to
+ /// std::string, or there should be an overload of std::string::operator+=()
+ /// that accepts the argument explicitly.
+ template <typename Sep, typename... Args>
+ inline std::string join_items(Sep Separator, Args &&... Items) {
+ std::string Result;
+ if (sizeof...(Items) == 0)
+ return Result;
+
+ size_t NS = detail::join_one_item_size(Separator);
+ size_t NI = detail::join_items_size(std::forward<Args>(Items)...);
+ Result.reserve(NI + (sizeof...(Items) - 1) * NS + 1);
+ detail::join_items_impl(Result, Separator, std::forward<Args>(Items)...);
+ return Result;
+ }
+
+ /// A helper class to return the specified delimiter string after the first
+ /// invocation of operator std::string_ref(). Used to generate a comma-separated
+ /// list from a loop like so:
+ ///
+ /// \code
+ /// ListSeparator LS;
+ /// for (auto &I : C)
+ /// OS << LS << I.getName();
+ /// \end
+ class ListSeparator {
+ bool First = true;
+ std::string_ref Separator;
+
+ public:
+ ListSeparator( std::string_ref Separator = ", ") : Separator(Separator) {}
+ operator std::string_ref() {
+ if (First) {
+ First = false;
+ return {};
+ }
+ return Separator;
+ }
+ };
+
+} // end namespace lsp
+
+namespace lsp{
+
+// Is <contents a plausible start to an HTML tag?
+// Contents may not be the rest of the line, but it's the rest of the plain
+// text, so we expect to see at least the tag name.
+bool looksLikeTag(std::string_ref& Contents) {
+ if (Contents.empty())
+ return false;
+ if (Contents.front() == '!' || Contents.front() == '?' ||
+ Contents.front() == '/')
+ return true;
+ // Check the start of the tag name.
+ if (!lsp::isAlpha(Contents.front()))
+ return false;
+ // Drop rest of the tag name, and following whitespace.
+ Contents = Contents
+ .drop_while([](char C) {
+ return lsp::isAlnum(C) || C == '-' || C == '_' || C == ':';
+ })
+ .drop_while(lsp::isSpace);
+ // The rest of the tag consists of attributes, which have restrictive names.
+ // If we hit '=', all bets are off (attribute values can contain anything).
+ for (; !Contents.empty(); Contents = Contents.drop_front()) {
+ if (lsp::isAlnum(Contents.front()) || lsp::isSpace(Contents.front()))
+ continue;
+ if (Contents.front() == '>' || Contents.start_with("/>"))
+ return true; // May close the tag.
+ if (Contents.front() == '=')
+ return true; // Don't try to parse attribute values.
+ return false; // Random punctuation means this isn't a tag.
+ }
+ return true; // Potentially incomplete tag.
+}
+
+// Tests whether C should be backslash-escaped in markdown.
+// The string being escaped is Before + C + After. This is part of a paragraph.
+// StartsLine indicates whether `Before` is the start of the line.
+// After may not be everything until the end of the line.
+//
+// It's always safe to escape punctuation, but want minimal escaping.
+// The strategy is to escape the first character of anything that might start
+// a markdown grammar construct.
+bool needsLeadingEscape(char C, std::string_ref Before, std::string_ref After,
+ bool StartsLine) {
+
+ auto RulerLength = [&]() -> /*Length*/ unsigned {
+ if (!StartsLine || !Before.empty())
+ return false;
+ std::string_ref A = After.trim_right();
+ return std::all_of(A.begin(),A.end(), [C](char D) { return C == D; }) ? 1 + A.size() : 0;
+ };
+ auto IsBullet = [&]() {
+ return StartsLine && Before.empty() &&
+ (After.empty() || After.start_with(" "));
+ };
+ auto SpaceSurrounds = [&]() {
+ return (After.empty() || std::isspace(After.front())) &&
+ (Before.empty() || std::isspace(Before.back()));
+ };
+
+ auto WordSurrounds = [&]() {
+ return (!After.empty() && std::isalnum(After.front())) &&
+ (!Before.empty() && std::isalnum(Before.back()));
+ };
+
+ switch (C) {
+ case '\\': // Escaped character.
+ return true;
+ case '`': // Code block or inline code
+ // Any number of backticks can delimit an inline code block that can end
+ // anywhere (including on another line). We must escape them all.
+ return true;
+ case '~': // Code block
+ return StartsLine && Before.empty() && After.start_with("~~");
+ case '#': { // ATX heading.
+ if (!StartsLine || !Before.empty())
+ return false;
+ std::string_ref& Rest = After.trim_left(C);
+ return Rest.empty() || Rest.start_with(" ");
+ }
+ case ']': // Link or link reference.
+ // We escape ] rather than [ here, because it's more constrained:
+ // ](...) is an in-line link
+ // ]: is a link reference
+ // The following are only links if the link reference exists:
+ // ] by itself is a shortcut link
+ // ][...] is an out-of-line link
+ // Because we never emit link references, we don't need to handle these.
+ return After.start_with(":") || After.start_with("(");
+ case '=': // Setex heading.
+ return RulerLength() > 0;
+ case '_': // Horizontal ruler or matched delimiter.
+ if (RulerLength() >= 3)
+ return true;
+ // Not a delimiter if surrounded by space, or inside a word.
+ // (The rules at word boundaries are subtle).
+ return !(SpaceSurrounds() || WordSurrounds());
+ case '-': // Setex heading, horizontal ruler, or bullet.
+ if (RulerLength() > 0)
+ return true;
+ return IsBullet();
+ case '+': // Bullet list.
+ return IsBullet();
+ case '*': // Bullet list, horizontal ruler, or delimiter.
+ return IsBullet() || RulerLength() >= 3 || !SpaceSurrounds();
+ case '<': // HTML tag (or autolink, which we choose not to escape)
+ return looksLikeTag(After);
+ case '>': // Quote marker. Needs escaping at start of line.
+ return StartsLine && Before.empty();
+ case '&': { // HTML entity reference
+ auto End = After.find(';');
+ if (End == std::string_ref::npos)
+ return false;
+ std::string_ref Content = After.substr(0, End);
+ if (Content.consume_front("#"))
+ {
+ if (Content.consume_front("x") || Content.consume_front("X"))
+ {
+ return std::all_of(Content.begin(),Content.end(), lsp::isHexDigit);
+ }
+
+ return std::all_of(Content.begin(), Content.end(), [](char c)
+ {
+ return lsp::isDigit(c);
+ });
+ }
+ return std::all_of(Content.begin(), Content.end(), [](char c)
+ {
+ return lsp::isAlpha(c);
+ });
+ }
+ case '.': // Numbered list indicator. Escape 12. -> 12\. at start of line.
+ case ')':
+ return StartsLine && !Before.empty() &&
+ std::all_of(Before.begin(), Before.end(), [](char c)
+ {
+ return lsp::isDigit(c);
+ }) && After.start_with(" ");
+ default:
+ return false;
+ }
+}
+
+/// Escape a markdown text block. Ensures the punctuation will not introduce
+/// any of the markdown constructs.
+ std::string_ref renderText(const std::string_ref& Input, bool StartsLine) {
+ std::string_ref R;
+ for (unsigned I = 0; I < Input.size(); ++I) {
+ if (needsLeadingEscape(Input[I], Input.substr(0, I), Input.substr(I + 1),
+ StartsLine))
+ R.push_back('\\');
+ R.push_back(Input[I]);
+ }
+ return R;
+}
+
+/// Renders \p Input as an inline block of code in markdown. The returned value
+/// is surrounded by backticks and the inner contents are properly escaped.
+ std::string_ref renderInlineBlock(const std::string_ref& Input) {
+ std::string_ref R;
+ // Double all backticks to make sure we don't close the inline block early.
+ for (size_t From = 0; From < Input.size();) {
+ size_t Next = Input.find("`", From);
+ R += Input.substr(From, Next - From);
+ if (Next == std::string_ref::npos)
+ break;
+ R += "``"; // double the found backtick.
+
+ From = Next + 1;
+ }
+ // If results starts with a backtick, add spaces on both sides. The spaces
+ // are ignored by markdown renderers.
+ if (std::string_ref(R).start_with("`") || std::string_ref(R).end_with("`"))
+ return "` " + std::move(R) + " `";
+ // Markdown render should ignore first and last space if both are there. We
+ // add an extra pair of spaces in that case to make sure we render what the
+ // user intended.
+ if (std::string_ref(R).start_with(" ") && std::string_ref(R).end_with(" "))
+ return "` " + std::move(R) + " `";
+ return "`" + std::move(R) + "`";
+}
+
+/// Get marker required for \p Input to represent a markdown codeblock. It
+/// consists of at least 3 backticks(`). Although markdown also allows to use
+/// tilde(~) for code blocks, they are never used.
+ std::string_ref getMarkerForCodeBlock(const std::string_ref& Input) {
+ // Count the maximum number of consecutive backticks in \p Input. We need to
+ // start and end the code block with more.
+ unsigned MaxBackticks = 0;
+ unsigned Backticks = 0;
+ for (char C : Input) {
+ if (C == '`') {
+ ++Backticks;
+ continue;
+ }
+ MaxBackticks = std::max(MaxBackticks, Backticks);
+ Backticks = 0;
+ }
+ MaxBackticks = std::max(Backticks, MaxBackticks);
+ // Use the corresponding number of backticks to start and end a code block.
+ return std::string_ref(/*Repeat=*/std::max(3u, MaxBackticks + 1), '`');
+}
+
+ /// SplitString - Split up the specified string according to the specified
+/// delimiters, appending the result fragments to the output list.
+ void SplitString(const std::string& Source,
+ std::vector<std::string_ref>& OutFragments,
+ std::string Delimiters = " \t\n\v\f\r")
+{
+ boost::split(OutFragments, Source, boost::is_any_of(Delimiters));
+}
+
+
+// Trims the input and concatenates whitespace blocks into a single ` `.
+ std::string_ref canonicalizeSpaces(const std::string_ref& Input) {
+ std::vector<std::string_ref> Words;
+ SplitString(Input, Words);
+
+ return lsp::join(Words, " ");
+}
+
+
+ std::string_ref renderBlocks( std::vector<Block*>&& Children,
+ void (Block::* RenderFunc)(std::ostringstream&) const) {
+ std::string_ref R;
+ std::ostringstream OS(R);
+
+ std::vector<int> v{ 1, 2, 3 };
+
+ // Trim rulers.
+ Children.erase(std::remove_if(Children.begin(), Children.end(), [](const Block* C)
+ {
+ return C->isRuler();
+ }), Children.end());
+
+ bool LastBlockWasRuler = true;
+ for (const auto& C : Children) {
+ if (C->isRuler() && LastBlockWasRuler)
+ continue;
+ LastBlockWasRuler = C->isRuler();
+ ((*C).*RenderFunc)(OS);
+ }
+
+ // Get rid of redundant empty lines introduced in plaintext while imitating
+ // padding in markdown.
+ std::string_ref AdjustedResult;
+ std::string_ref TrimmedText(OS.str());
+ TrimmedText = TrimmedText.trim();
+
+ std::copy_if(TrimmedText.begin(), TrimmedText.end(),
+ std::back_inserter(AdjustedResult),
+ [&TrimmedText](const char& C) {
+ return !std::string_ref(TrimmedText.data(),
+ &C - TrimmedText.data() + 1)
+ // We allow at most two newlines.
+ .end_with("\n\n\n");
+ });
+
+ return AdjustedResult;
+ };
+ std::string_ref renderBlocks(const std::vector<std::unique_ptr<Block> >& children,
+ void (Block::* renderFunc)(std::ostringstream&) const)
+ {
+ std::vector<Block*> temp(children.size(), nullptr);
+ for(size_t i = 0 ; i < children.size() ; ++i)
+ {
+ temp[i]=(children[i].get());
+ }
+ return renderBlocks(std::move(temp), renderFunc);
+ }
+// Separates two blocks with extra spacing. Note that it might render strangely
+// in vscode if the trailing block is a codeblock, see
+// https://github.com/microsoft/vscode/issues/88416 for details.
+class Ruler : public Block {
+public:
+ void renderMarkdown(std::ostringstream &OS) const override {
+ // Note that we need an extra new line before the ruler, otherwise we might
+ // make previous block a title instead of introducing a ruler.
+ OS << "\n---\n";
+ }
+ void renderPlainText(std::ostringstream &OS) const override { OS << '\n'; }
+ std::unique_ptr<Block> clone() const override {
+ return std::make_unique<Ruler>(*this);
+ }
+ bool isRuler() const override { return true; }
+};
+
+class CodeBlock : public Block {
+public:
+ void renderMarkdown(std::ostringstream &OS) const override {
+ std::string_ref Marker = getMarkerForCodeBlock(Contents);
+ // No need to pad from previous blocks, as they should end with a new line.
+ OS << Marker << Language << '\n' << Contents << '\n' << Marker << '\n';
+ }
+
+ void renderPlainText(std::ostringstream &OS) const override {
+ // In plaintext we want one empty line before and after codeblocks.
+ OS << '\n' << Contents << "\n\n";
+ }
+
+ std::unique_ptr<Block> clone() const override {
+ return std::make_unique<CodeBlock>(*this);
+ }
+
+ CodeBlock( std::string_ref Contents, std::string_ref Language)
+ : Contents(std::move(Contents)), Language(std::move(Language)) {}
+
+private:
+
+ std::string_ref Contents;
+ std::string_ref Language;
+};
+
+// Inserts two spaces after each `\n` to indent each line. First line is not
+// indented.
+ std::string_ref indentLines(const std::string_ref& Input) {
+ assert(!Input.end_with("\n") && "Input should've been trimmed.");
+ std::string_ref IndentedR;
+ // We'll add 2 spaces after each new line.
+ IndentedR.reserve(Input.size() + Input.count("\n") * 2);
+ for (char C : Input) {
+ IndentedR += C;
+ if (C == '\n')
+ IndentedR.append(" ");
+ }
+ return IndentedR;
+}
+
+class Heading : public Paragraph {
+public:
+ Heading(size_t Level) : Level(Level) {}
+ void renderMarkdown(std::ostringstream &OS) const override {
+ OS << std::string_ref(Level, '#') << ' ';
+ Paragraph::renderMarkdown(OS);
+ }
+
+private:
+ size_t Level;
+};
+
+
+
+
+
+ std::string_ref Block::asMarkdown() const {
+ std::string_ref R;
+ std::ostringstream OS(R);
+ renderMarkdown(OS);
+ return std::string_ref(OS.str()).trim();
+}
+
+ std::string_ref Block::asPlainText() const {
+ std::string_ref R;
+ std::ostringstream OS(R);
+ renderPlainText(OS);
+ return std::string_ref(OS.str()).trim().c_str();
+}
+
+ void Paragraph::renderMarkdown(std::ostringstream& OS) const {
+ bool NeedsSpace = false;
+ bool HasChunks = false;
+ for (auto& C : Chunks) {
+ if (C.SpaceBefore || NeedsSpace)
+ OS << " ";
+ switch (C.Kind) {
+ case Chunk::PlainText:
+ OS << renderText(C.Contents, !HasChunks);
+ break;
+ case Chunk::InlineCode:
+ OS << renderInlineBlock(C.Contents);
+ break;
+ }
+ HasChunks = true;
+ NeedsSpace = C.SpaceAfter;
+ }
+ // Paragraphs are translated into markdown lines, not markdown paragraphs.
+ // Therefore it only has a single linebreak afterwards.
+ // VSCode requires two spaces at the end of line to start a new one.
+ OS << " \n";
+ }
+
+ std::unique_ptr<Block> Paragraph::clone() const {
+ return std::make_unique<Paragraph>(*this);
+ }
+
+ /// Choose a marker to delimit `Text` from a prioritized list of options.
+ /// This is more readable than escaping for plain-text.
+ std::string_ref chooseMarker(std::vector<std::string_ref> Options,
+ const std::string_ref& Text)
+ {
+ // Prefer a delimiter whose characters don't appear in the text.
+ for (std::string_ref& S : Options)
+ if (Text.find_first_of(S) == std::string_ref::npos)
+ return S;
+ return Options.front();
+ }
+
+ void Paragraph::renderPlainText(std::ostringstream& OS) const {
+ bool NeedsSpace = false;
+ for (auto& C : Chunks) {
+ if (C.SpaceBefore || NeedsSpace)
+ OS << " ";
+ std::string_ref Marker = "";
+ if (C.Preserve && C.Kind == Chunk::InlineCode)
+ Marker = chooseMarker({ "`", "'", "\"" }, C.Contents);
+ OS << Marker << C.Contents << Marker;
+ NeedsSpace = C.SpaceAfter;
+ }
+ OS << '\n';
+ }
+
+ void BulletList::renderMarkdown(std::ostringstream& OS) const {
+ for (auto& D : Items) {
+ // Instead of doing this we might prefer passing Indent to children to get
+ // rid of the copies, if it turns out to be a bottleneck.
+
+ OS << "- ";
+ OS << indentLines(D.asMarkdown()) << '\n';
+ }
+ // We need a new line after list to terminate it in markdown.
+ OS << '\n';
+ }
+
+ void BulletList::renderPlainText(std::ostringstream& OS) const {
+ for (auto& D : Items) {
+ // Instead of doing this we might prefer passing Indent to children to get
+ // rid of the copies, if it turns out to be a bottleneck.
+ OS << "- " << indentLines(D.asPlainText()) << '\n';
+ }
+ }
+
+ Paragraph& Paragraph::appendSpace() {
+ if (!Chunks.empty())
+ Chunks.back().SpaceAfter = true;
+ return *this;
+ }
+
+ Paragraph& Paragraph::appendText(const std::string_ref& Text) {
+ std::string_ref Norm = canonicalizeSpaces(Text);
+ if (Norm.empty())
+ return *this;
+ Chunks.emplace_back();
+ Chunk& C = Chunks.back();
+ C.Contents = std::move(Norm);
+ C.Kind = Chunk::PlainText;
+
+ C.SpaceBefore = std::isspace(Text.front());
+ C.SpaceAfter = std::isspace(Text.back());
+ return *this;
+ }
+
+ Paragraph& Paragraph::appendCode(const std::string_ref& Code, bool Preserve) {
+ bool AdjacentCode =
+ !Chunks.empty() && Chunks.back().Kind == Chunk::InlineCode;
+ std::string_ref Norm = canonicalizeSpaces(Code);
+ if (Norm.empty())
+ return *this;
+ Chunks.emplace_back();
+ Chunk& C = Chunks.back();
+ C.Contents = std::move(Norm);
+ C.Kind = Chunk::InlineCode;
+ C.Preserve = Preserve;
+ // Disallow adjacent code spans without spaces, markdown can't render them.
+ C.SpaceBefore = AdjacentCode;
+ return *this;
+ }
+
+ std::unique_ptr<Block> BulletList::clone() const {
+ return std::make_unique<BulletList>(*this);
+ }
+
+ class Document& BulletList::addItem() {
+ Items.emplace_back();
+ return Items.back();
+ }
+
+ Document& Document::operator=(const Document& Other) {
+ Children.clear();
+ for (const auto& C : Other.Children)
+ Children.push_back(C->clone());
+ return *this;
+ }
+
+ void Document::append(Document Other) {
+ std::move(Other.Children.begin(), Other.Children.end(),
+ std::back_inserter(Children));
+ }
+
+ Paragraph& Document::addParagraph() {
+ Children.push_back(std::make_unique<Paragraph>());
+ return *static_cast<Paragraph*>(Children.back().get());
+ }
+
+ void Document::addRuler() { Children.push_back(std::make_unique<Ruler>()); }
+
+ void Document::addCodeBlock(std::string_ref Code, std::string_ref Language) {
+ Children.emplace_back(
+ std::make_unique<CodeBlock>(std::move(Code), std::move(Language)));
+ }
+
+ std::string_ref Document::asMarkdown() const {
+ return renderBlocks(Children, &Block::renderMarkdown);
+ }
+
+ std::string_ref Document::asPlainText() const {
+ return renderBlocks(Children, &Block::renderPlainText);
+ }
+
+ BulletList& Document::addBulletList() {
+ Children.emplace_back(std::make_unique<BulletList>());
+ return *static_cast<BulletList*>(Children.back().get());
+ }
+
+ Paragraph& Document::addHeading(size_t Level) {
+ assert(Level > 0);
+ Children.emplace_back(std::make_unique<Heading>(Level));
+ return *static_cast<Paragraph*>(Children.back().get());
+ }
+ }; \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.h b/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.h
new file mode 100644
index 0000000000..92d773db0c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/Markup.h
@@ -0,0 +1,119 @@
+#pragma once
+#include <cctype>
+#include <clocale>
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include "string_ref.h"
+
+namespace lsp
+{
+
+/// Holds text and knows how to lay it out. Multiple blocks can be grouped to
+/// form a document. Blocks include their own trailing newlines, std::string_ref
+/// should trim them if need be.
+class Block {
+public:
+ virtual void renderMarkdown(std::ostringstream &OS) const = 0;
+ virtual void renderPlainText(std::ostringstream &OS) const = 0;
+ virtual std::unique_ptr<Block> clone() const = 0;
+ std::string_ref asMarkdown() const;
+ std::string_ref asPlainText() const;
+
+ virtual bool isRuler() const { return false; }
+ virtual ~Block() = default;
+};
+
+/// Represents parts of the markup that can contain strings, like inline code,
+/// code block or plain text.
+/// One must introduce different paragraphs to create separate blocks.
+class Paragraph : public Block {
+public:
+ void renderMarkdown(std::ostringstream &OS) const override;
+ void renderPlainText(std::ostringstream &OS) const override;
+ std::unique_ptr<Block> clone() const override;
+
+ /// Append plain text to the end of the string.
+ Paragraph &appendText(const std::string_ref& Text);
+
+ /// Append inline code, this translates to the ` block in markdown.
+ /// \p Preserve indicates the code span must be apparent even in plaintext.
+ Paragraph &appendCode(const std::string_ref& Code, bool Preserve = false);
+
+ /// Ensure there is space between the surrounding chunks.
+ /// Has no effect at the beginning or end of a paragraph.
+ Paragraph &appendSpace();
+
+private:
+ struct Chunk {
+ enum {
+ PlainText,
+ InlineCode,
+ } Kind = PlainText;
+ // Preserve chunk markers in plaintext.
+ bool Preserve = false;
+ std::string_ref Contents;
+ // Whether this chunk should be surrounded by whitespace.
+ // Consecutive SpaceAfter and SpaceBefore will be collapsed into one space.
+ // Code spans don't usually set this: their spaces belong "inside" the span.
+ bool SpaceBefore = false;
+ bool SpaceAfter = false;
+ };
+ std::vector<Chunk> Chunks;
+};
+
+/// Represents a sequence of one or more documents. Knows how to print them in a
+/// list like format, e.g. by prepending with "- " and indentation.
+class BulletList : public Block {
+public:
+ void renderMarkdown(std::ostringstream &OS) const override;
+ void renderPlainText(std::ostringstream &OS) const override;
+ std::unique_ptr<Block> clone() const override;
+
+ class Document &addItem();
+
+private:
+ std::vector<class Document> Items;
+};
+
+/// A format-agnostic representation for structured text. Allows rendering into
+/// markdown and plaintext.
+class Document {
+public:
+ Document() = default;
+ Document(const Document &Other) { *this = Other; }
+ Document &operator=(const Document &);
+ Document(Document &&) = default;
+ Document &operator=(Document &&) = default;
+
+ void append(Document Other);
+
+ /// Adds a semantical block that will be separate from others.
+ Paragraph &addParagraph();
+ /// Inserts a horizontal separator to the document.
+ void addRuler();
+ /// Adds a block of code. This translates to a ``` block in markdown. In plain
+ /// text representation, the code block will be surrounded by newlines.
+ void addCodeBlock( std::string_ref Code, std::string_ref Language = "cpp");
+ /// Heading is a special type of paragraph that will be prepended with \p
+ /// Level many '#'s in markdown.
+ Paragraph &addHeading(size_t Level);
+
+ BulletList &addBulletList();
+
+ /// Doesn't contain any trailing newlines.
+ /// We try to make the markdown human-readable, e.g. avoid extra escaping.
+ /// At least one client (coc.nvim) displays the markdown verbatim!
+ std::string_ref asMarkdown() const;
+ /// Doesn't contain any trailing newlines.
+ std::string_ref asPlainText() const;
+
+private:
+ std::vector<std::unique_ptr<Block>> Children;
+};
+
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/string_ref.h b/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/string_ref.h
new file mode 100644
index 0000000000..d7ee423944
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/Markup/string_ref.h
@@ -0,0 +1,1059 @@
+
+#pragma once
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <stdarg.h>
+#include<functional>
+
+#ifndef _WIN32
+#include <cstring>
+#endif
+namespace std
+{
+
+ /**
+ * An extension of STL's string providing additional functionality that is often availiable in
+ * higher-level languages such as Python.
+ */
+ class string_ref : public string
+ {
+ public:
+
+ //static unsigned GetAutoSenseRadix(string_ref& Str) {
+ // if (Str.empty())
+ // return 10;
+
+ // if (Str.start_with("0x") || Str.start_with("0X")) {
+ // Str = Str.substr(2);
+ // return 16;
+ // }
+
+ // if (Str.start_with("0b") || Str.start_with("0B")) {
+ // Str = Str.substr(2);
+ // return 2;
+ // }
+
+ // if (Str.start_with("0o")) {
+ // Str = Str.substr(2);
+ // return 8;
+ // }
+
+ // if (Str[0] == '0' && Str.size() > 1 && std::isdigit(Str[1])) {
+ // Str = Str.substr(1);
+ // return 8;
+ // }
+
+ // return 10;
+ //}
+
+ //static bool consumeUnsignedInteger(string_ref& Str, unsigned Radix,
+ // unsigned long long& Result) {
+ // // Autosense radix if not specified.
+ // if (Radix == 0)
+ // Radix = GetAutoSenseRadix(Str);
+
+ // // Empty strings (after the radix autosense) are invalid.
+ // if (Str.empty()) return true;
+
+ // // Parse all the bytes of the string given this radix. Watch for overflow.
+ // string_ref Str2 = Str;
+ // Result = 0;
+ // while (!Str2.empty()) {
+ // unsigned CharVal;
+ // if (Str2[0] >= '0' && Str2[0] <= '9')
+ // CharVal = Str2[0] - '0';
+ // else if (Str2[0] >= 'a' && Str2[0] <= 'z')
+ // CharVal = Str2[0] - 'a' + 10;
+ // else if (Str2[0] >= 'A' && Str2[0] <= 'Z')
+ // CharVal = Str2[0] - 'A' + 10;
+ // else
+ // break;
+
+ // // If the parsed value is larger than the integer radix, we cannot
+ // // consume any more characters.
+ // if (CharVal >= Radix)
+ // break;
+
+ // // Add in this character.
+ // unsigned long long PrevResult = Result;
+ // Result = Result * Radix + CharVal;
+
+ // // Check for overflow by shifting back and seeing if bits were lost.
+ // if (Result / Radix < PrevResult)
+ // return true;
+
+ // Str2 = Str2.substr(1);
+ // }
+
+ // // We consider the operation a failure if no characters were consumed
+ // // successfully.
+ // if (Str.size() == Str2.size())
+ // return true;
+
+ // Str = Str2;
+ // return false;
+ //}
+
+ //static bool consumeSignedInteger(string_ref& Str, unsigned Radix,
+ // long long& Result) {
+ // unsigned long long ULLVal;
+
+ // // Handle positive strings first.
+ // if (Str.empty() || Str.front() != '-') {
+ // if (consumeUnsignedInteger(Str, Radix, ULLVal) ||
+ // // Check for value so large it overflows a signed value.
+ // (long long)ULLVal < 0)
+ // return true;
+ // Result = ULLVal;
+ // return false;
+ // }
+
+ // // Get the positive part of the value.
+ // string_ref Str2 = Str.drop_front(1);
+ // if (consumeUnsignedInteger(Str2, Radix, ULLVal) ||
+ // // Reject values so large they'd overflow as negative signed, but allow
+ // // "-0". This negates the unsigned so that the negative isn't undefined
+ // // on signed overflow.
+ // (long long)-ULLVal > 0)
+ // return true;
+
+ // Str = Str2;
+ // Result = -ULLVal;
+ // return false;
+ //}
+
+ ///// GetAsUnsignedInteger - Workhorse method that converts a integer character
+ ///// sequence of radix up to 36 to an unsigned long long value.
+ //static bool getAsUnsignedInteger(string_ref Str, unsigned Radix,
+ // unsigned long long& Result) {
+ // if (consumeUnsignedInteger(Str, Radix, Result))
+ // return true;
+
+ // // For getAsUnsignedInteger, we require the whole string to be consumed or
+ // // else we consider it a failure.
+ // return !Str.empty();
+ //}
+
+ //static bool getAsSignedInteger(string_ref Str, unsigned Radix,
+ // long long& Result) {
+ // if (consumeSignedInteger(Str, Radix, Result))
+ // return true;
+
+ // // For getAsSignedInteger, we require the whole string to be consumed or else
+ // // we consider it a failure.
+ // return !Str.empty();
+ //}
+
+
+ ///// Parse the current string as an integer of the specified radix. If
+ ///// \p Radix is specified as zero, this does radix autosensing using
+ ///// extended C rules: 0 is octal, 0x is hex, 0b is binary.
+ /////
+ ///// If the string is invalid or if only a subset of the string is valid,
+ ///// this returns true to signify the error. The string is considered
+ ///// erroneous if empty or if it overflows T.
+ //template <typename T>
+ //std::enable_if_t<std::numeric_limits<T>::is_signed, bool>
+ // getAsInteger(unsigned Radix, T& Result) const {
+ // long long LLVal;
+ // if (getAsSignedInteger(*this, Radix, LLVal) ||
+ // static_cast<T>(LLVal) != LLVal)
+ // return true;
+ // Result = LLVal;
+ // return false;
+ //}
+
+ //template <typename T>
+ //std::enable_if_t<!std::numeric_limits<T>::is_signed, bool>
+ // getAsInteger(unsigned Radix, T& Result) const {
+ // unsigned long long ULLVal;
+ // // The additional cast to unsigned long long is required to avoid the
+ // // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type
+ // // 'unsigned __int64' when instantiating getAsInteger with T = bool.
+ // if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
+ // static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
+ // return true;
+ // Result = ULLVal;
+ // return false;
+ //}
+
+
+
+ /**`
+ * Default constructor
+ *
+ * Constructs an empty string_ref ("")
+ */
+ string_ref() : string() { }
+
+ /**
+ * Duplicate the STL string copy constructor
+ *
+ * @param[in] s The string to copy
+ * @param[in] pos The starting position in the string to copy from
+ * @param[in] n The number of characters to copy
+ */
+ string_ref(const string &s, size_type pos = 0, size_type n = npos) : string(s, pos, npos) { }
+
+ /**
+ * Construct an string_ref from a null-terminated character array
+ *
+ * @param[in] s The character array to copy into the new string
+ */
+ string_ref(const value_type *s) : string(s) { }
+
+ /**
+ * Construct an string_ref from a character array and a length
+ *
+ * @param[in] s The character array to copy into the new string
+ * @param[in] n The number of characters to copy
+ */
+ string_ref(const value_type *s, size_type n) : string(s, n) { }
+
+ /**
+ * Create an string_ref with @p n copies of @p c
+ *
+ * @param[in] n The number of copies
+ * @param[in] c The character to copy @p n times
+ */
+ string_ref(size_type n, value_type c) : string(n, c) { }
+
+ /**
+ * Create a string from a range
+ *
+ * @param[in] first The first element to copy in
+ * @param[in] last The last element to copy in
+ */
+ template <class InputIterator>
+ string_ref(InputIterator first, InputIterator last) : string(first, last) { }
+
+ /**
+ * The destructor
+ */
+ ~string_ref() { }
+
+ /**
+ * Split a string by whitespace
+ *
+ * @return A vector of strings, each of which is a substring of the string
+ */
+ vector<string_ref> split(size_type limit = npos) const
+ {
+ vector<string_ref> v;
+
+ const_iterator
+ i = begin(),
+ last = i;
+ for (; i != end(); i++)
+ {
+ if (*i == ' ' || *i == '\n' || *i == '\t' || *i == '\r')
+ {
+ if (i + 1 != end() && (i[1] == ' ' || i[1] == '\n' || i[1] == '\t' || i[1] == '\r'))
+ continue;
+ v.push_back(string_ref(last, i));
+ last = i + 1;
+ if (v.size() >= limit - 1)
+ {
+ v.push_back(string_ref(last, end()));
+ return v;
+ }
+ }
+ }
+
+ if (last != i)
+ v.push_back(string_ref(last, i));
+
+ return v;
+ }
+
+ /**
+ * Split a string by a character
+ *
+ * Returns a vector of ext_strings, each of which is a substring of the string formed by splitting
+ * it on boundaries formed by the character @p separator. If @p limit is set, the returned vector
+ * will contain a maximum of @p limit elements with the last element containing the rest of
+ * the string.
+ *
+ * If @p separator is not found in the string, a single element will be returned in the vector
+ * containing the entire string.
+ *
+ * The separators are removed from the output
+ *
+ * @param[in] separator The character separator to split the string on
+ * @param[in] limit The maximum number of output elements
+ * @return A vector of strings, each of which is a substring of the string
+ *
+ * @section split_ex Example
+ * @code
+ * std::string_ref s("This|is|a|test.");
+ * std::vector<std::string_ref> v = s.split('|');
+ * std::copy(v.begin(), v.end(), std::ostream_iterator<std::string_ref>(std::cout, "\n"));
+ *
+ * This
+ * is
+ * a
+ * test.
+ * @endcode
+ */
+ vector<string_ref> split(value_type separator, size_type limit = npos) const
+ {
+ vector<string_ref> v;
+
+ const_iterator
+ i = begin(),
+ last = i;
+ for (; i != end(); i++)
+ {
+ if (*i == separator)
+ {
+ v.push_back(string_ref(last, i));
+ last = i + 1;
+ if (v.size() >= limit - 1)
+ {
+ v.push_back(string_ref(last, end()));
+ return v;
+ }
+ }
+ }
+
+ if (last != i)
+ v.push_back(string_ref(last, i));
+
+ return v;
+ }
+
+ /**
+ * Split a string by another string
+ *
+ * Returns a vector of ext_strings, each of which is a substring of the string formed by
+ * splitting it on boundaries formed by the string @p separator. If @p limit is set, the
+ * returned vector will contain a maximum of @p limit elements with the last element
+ * containing the rest of the string.
+ *
+ * If @p separator is not found in the string, a single element will be returned in the
+ * vector containing the entire string.
+ *
+ * The separators are removed from the output
+ *
+ * @param[in] separator The string separator to split the string on
+ * @param[in] limit The maximum number of output elements
+ * @return A vector of strings, each of which is a substring of the string
+ *
+ * @ref split_ex
+ */
+ vector<string_ref> split(const string &separator, size_type limit = npos) const
+ {
+ vector<string_ref> v;
+
+ const_iterator
+ i = begin(),
+ last = i;
+ for (; i != end(); i++)
+ {
+ if (string(i, i + separator.length()) == separator)
+ {
+ v.push_back(string_ref(last, i));
+ last = i + separator.length();
+
+ if (v.size() >= limit - 1)
+ {
+ v.push_back(string_ref(last, end()));
+ return v;
+ }
+ }
+ }
+
+ if (last != i)
+ v.push_back(string_ref(last, i));
+
+ return v;
+ }
+
+ /**
+ * Convert a string into an integer
+ *
+ * Convert the initial portion of a string into a signed integer. Once a non-numeric
+ * character is reached, the remainder of @p string is ignored and the integer that was
+ * read returned.
+ *
+ * @param s The string to convert
+ * @return The integer converted from @p string
+ */
+ static long int integer(const string &s)
+ {
+ long int retval = 0;
+ bool neg = false;
+
+ for (const_iterator i = s.begin(); i != s.end(); i++)
+ {
+ if (i == s.begin())
+ {
+ if (*i == '-')
+ {
+ neg = true;
+ continue;
+ }
+ else if (*i == '+')
+ continue;
+ }
+ if (*i >= '0' && *i <= '9')
+ {
+ retval *= 10;
+ retval += *i - '0';
+ }
+ else
+ break;
+ }
+
+ if (neg)
+ retval *= -1;
+
+ return retval;
+ }
+
+ /**
+ * Convert the string to an integer
+ *
+ * Convert the initial portion of the string into a signed integer. Once a non-numeric
+ * character is reached, the remainder of the string is ignored and the integer that had
+ * been read thus far is returned.
+ *
+ * @return The integer converted from the string
+ */
+ long int integer() const
+ {
+ return integer(*this);
+ }
+
+ /**
+ * Split a string into chunks of size @p chunklen. Returns a vector of strings.
+ *
+ * Splits a string into chunks of the given size. The final chunk may not fill its
+ * entire allocated number of characters.
+ *
+ * @param[in] chunklen The number of characters per chunk
+ * @return A vector of strings, each of length <= chunklen
+ *
+ * @section chunk_split-ex Example
+ * @code
+ * std::string_ref s("abcdefghijk");
+ * std::vector<std::string_ref> v = s.chunk_split(3);
+ * std::copy(v.begin(), v.end(), ostream_iterator<std::string_ref>(cout, " "));
+ *
+ * abc def ghi jk
+ * @endcode
+ */
+ vector<string_ref> chunk_split(size_type chunklen) const
+ {
+ vector<string_ref> retval;
+ retval.reserve(size() / chunklen + 1);
+
+ size_type count = 0;
+ const_iterator
+ i = begin(),
+ last = i;
+ for (; i != end(); i++, count++)
+ {
+ if (count == chunklen)
+ {
+ count = 0;
+ retval.push_back(string_ref(last, i));
+ last = i;
+ }
+ }
+
+ if (last != i)
+ retval.push_back(string_ref(last, i));
+
+ return retval;
+ }
+
+ /**
+ * Join a sequence of strings by some glue to create a new string
+ *
+ * Glue is not added to the end of the string.
+ *
+ * @pre [first, last) is a valid range
+ * @pre InputIterator is a model of STL's Input Iterator
+ * @pre InputIterator must point to a string type (std::string, std::string_ref, char *)
+ *
+ * @param[in] glue The glue to join strings with
+ * @param[in] first The beginning of the range to join
+ * @param[in] last The end of the range to join
+ * @return A string constructed of each element of the range connected together with @p glue
+ *
+ * @section join_ex Example
+ * @code
+ * std::vector<std::string_ref> v;
+ * v.push_back("This");
+ * v.push_back("is");
+ * v.push_back("a");
+ * v.push_back("test.");
+ * std::cout << std::string_ref::join("|", v.begin(), v.end()) << std::endl;
+ *
+ * This|is|a|test.
+ * @endcode
+ */
+ template <class InputIterator>
+ static string_ref join(const string &glue, InputIterator first, InputIterator last)
+ {
+ string_ref retval;
+
+ for (; first != last; ++first)
+ {
+ retval.append(*first);
+ retval.append(glue);
+ }
+ retval.erase(retval.length() - glue.length());
+
+ return retval;
+ }
+
+ /**
+ * Join a sequence of strings by some glue to create a new string
+ *
+ * @copydoc join
+ * @ref join_ex
+ */
+ template <class InputIterator>
+ static string_ref join(value_type glue, InputIterator first, InputIterator last)
+ {
+ string_ref retval;
+
+ for (; first != last; ++first)
+ {
+ retval.append(*first);
+ retval.append(1, glue);
+ }
+ retval.erase(retval.length() - 1);
+
+ return retval;
+ }
+
+ /**
+ * Search for any instances of @p needle and replace them with @p s
+ *
+ * @param[in] needle The string to replace
+ * @param[in] s The replacement string
+ * @return *this
+ * @post All instances of @p needle in the string are replaced with @p s
+ *
+ * @section replace-ex Example
+ * @code
+ * std::string_ref s("This is a test.");
+ * s.replace("is", "ere");
+ * std::cout << s << std::endl;
+ *
+ * There ere a test.
+ * @endcode
+ */
+ string_ref &replace(const string &needle, const string &s)
+ {
+ size_type
+ lastpos = 0,
+ thispos;
+
+ while ((thispos = find(needle, lastpos)) != npos)
+ {
+ string::replace(thispos, needle.length(), s);
+ lastpos = thispos + 1;
+ }
+ return *this;
+ }
+ string_ref &replace_first(const string &needle, const string &s)
+ {
+ size_type
+ lastpos = 0,
+ thispos;
+
+ if ((thispos = find(needle, lastpos)) != npos)
+ {
+ string::replace(thispos, needle.length(), s);
+ lastpos = thispos + 1;
+ }
+ return *this;
+ }
+ /**
+ * Search of any instances of @p needle and replace them with @p c
+ *
+ * @param[in] needle The character to replace
+ * @param[in] c The replacement character
+ * @return *this
+ * @post All instances of @p needle in the string are replaced with @p c
+ *
+ * @ref replace-ex
+ */
+ string_ref &replace(value_type needle, value_type c)
+ {
+ for (iterator i = begin(); i != end(); i++)
+ if (*i == needle)
+ *i = c;
+
+ return *this;
+ }
+
+ /**
+ * Repeat a string @p n times
+ *
+ * @param[in] n The number of times to repeat the string
+ * @return string_ref containing @p n copies of the string
+ *
+ * @section repeat-ex Example
+ * @code
+ * std::string_ref s("123");
+ * s = s * 3;
+ * std::cout << s << std::endl;
+ *
+ * 123123123
+ * @endcode
+ */
+ string_ref operator*(size_type n)
+ {
+ string_ref retval;
+ for (size_type i = 0; i < n; i++)
+ retval.append(*this);
+
+ return retval;
+ }
+
+ /**
+ * Convert the string to lowercase
+ *
+ * @return *this
+ * @post The string is converted to lowercase
+ */
+ string_ref &tolower()
+ {
+ for (iterator i = begin(); i != end(); i++)
+ if (*i >= 'A' && *i <= 'Z')
+ *i = (*i) + ('a' - 'A');
+ return *this;
+ }
+
+ /**
+ * Convert the string to uppercase
+ *
+ * @return *this
+ * @post The string is converted to uppercase
+ */
+ string_ref &toupper()
+ {
+ for (iterator i = begin(); i != end(); i++)
+ if (*i >= 'a' && *i <= 'z')
+ *i = (*i) - ('a' - 'A');
+ return *this;
+ }
+
+ /**
+ * Count the occurances of @p str in the string.
+ *
+ * @return The count of substrings @p str in the string
+ */
+ size_type count(const string &str) const
+ {
+ size_type
+ count = 0,
+ last = 0,
+ cur = 0;
+
+ while ((cur = find(str, last + 1)) != npos)
+ {
+ count++;
+ last = cur;
+ }
+
+ return count;
+ }
+
+ /**
+ * Determine if the string is alphanumeric
+ *
+ * @return true if the string contains only characters between a-z, A-Z and 0-9 and
+ * contains at least one character, else false
+ */
+ bool is_alnum() const
+ {
+ if (length() == 0)
+ return false;
+
+ for (const_iterator i = begin(); i != end(); i++)
+ {
+ if (*i < 'A' || *i > 'Z')
+ if (*i < '0' || *i > '9')
+ if (*i < 'a' || *i > 'z')
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Determine if the string is alphabetic only
+ *
+ * @return true of the string contains only characters between a-z and A-Z and contains at
+ * least one character, else false
+ */
+ bool is_alpha() const
+ {
+ if (length() == 0)
+ return false;
+
+ for (const_iterator i = begin(); i != end(); i++)
+ if (*i < 'A' || (*i > 'Z' && (*i < 'a' || *i > 'z')))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Determine if the string is numeric only
+ *
+ * @return true if the string contains only characters between 0-9 and contains at least
+ * one character, else false
+ */
+ bool is_numeric() const
+ {
+ if (length() == 0)
+ return false;
+
+ for (const_iterator i = begin(); i != end(); i++)
+ if (*i < '0' || *i > '9')
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Determine if a string is all lower case
+ *
+ * @return true if there is at least one character, and all characters are lowercase
+ * letters, else false
+ */
+ bool is_lower() const
+ {
+ if (length() == 0)
+ return false;
+
+ for (const_iterator i = begin(); i != end(); i++)
+ if (*i < 'a' || *i < 'z')
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Determine if a string is all upper case
+ *
+ * @return true if there is at least one character, and all characters are uppercase
+ * letters, else false
+ */
+ bool is_upper() const
+ {
+ if (length() == 0)
+ return false;
+
+ for (const_iterator i = begin(); i != end(); i++)
+ if (*i < 'A' || *i > 'Z')
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Swap the case of a string
+ *
+ * @post Converts all uppercase to lowercase, and all lowercase to uppercase in the string
+ * @return *this
+ */
+ string_ref &swapcase()
+ {
+ for (iterator i = begin(); i != end(); i++)
+ if (*i >= 'A' && *i <= 'Z')
+ *i += ('a' - 'A');
+ else if (*i >= 'a' && *i <= 'z')
+ *i -= ('a' - 'A');
+
+ return *this;
+ }
+
+ /*******************************************************************************
+ Function: std::string_ref::start_with
+ Access: public
+ Qualifier: const
+ Parameter: const string & str
+ Returns: bool
+
+ Purpose: is the string start with str
+ *******************************************************************************/
+ bool start_with(const string& str) const
+ {
+ return ( this->find(str) == 0 );
+ }
+
+ /// Return a string_ref equal to 'this' but with only the last \p N
+ /// elements remaining. If \p N is greater than the length of the
+ /// string, the entire string is returned.
+
+ string_ref take_back(size_t N = 1) const {
+ if (N >= size())
+ return *this;
+ return drop_front(size() - N);
+ }
+ /// Return a string_ref equal to 'this' but with the first \p N elements
+ /// dropped.
+
+ string_ref drop_front(size_t N = 1) const {
+ //assert(size() >= N && "Dropping more elements than exist");
+ return substr(N);
+ }
+
+
+
+ /// Return a string_ref equal to 'this' but with the last \p N elements
+ /// dropped.
+
+ string_ref drop_back(size_t N = 1) const {
+
+ return substr(0, size() - N);
+ }
+
+ /// Return a string_ref equal to 'this', but with all characters satisfying
+ /// the given predicate dropped from the beginning of the string.
+
+ string_ref drop_while(std::function<bool(char)> F) const {
+ return substr(std::find_if_not(begin(),end(),F)-begin());
+ }
+
+ /// Return a string_ref equal to 'this', but with all characters not
+ /// satisfying the given predicate dropped from the beginning of the string.
+
+ string_ref drop_until(std::function<bool(char)> F) const {
+ return substr(std::find_if(begin(), end(), F) - begin());
+ }
+
+ /// Returns true if this string_ref has the given prefix and removes that
+ /// prefix.
+ bool consume_front(string_ref Prefix) {
+ if (!start_with(Prefix))
+ return false;
+
+ *this = drop_front(Prefix.size());
+ return true;
+ }
+
+ /// Returns true if this string_ref has the given suffix and removes that
+ /// suffix.
+ bool consume_back(string_ref Suffix) {
+ if (!end_with(Suffix))
+ return false;
+
+ *this = drop_back(Suffix.size());
+ return true;
+ }
+
+ /*******************************************************************************
+ Function: std::string_ref::end_with
+ Access: public
+ Qualifier: const
+ Parameter: const string & str
+ Returns: bool
+
+ Purpose: is the string end with str
+ *******************************************************************************/
+ bool end_with(const string& str) const
+ {
+ if (str.length() > this->length())
+ {
+ return false;
+ }
+ size_type off = this->length() - str.length();
+ return ( find(str, off) == off);
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::format
+ Access: public
+ Qualifier:
+ Parameter: const char * format_string
+ Parameter: ...
+ Returns: string_ref&
+
+ Purpose: format the string
+ *******************************************************************************/
+ string_ref& format(const char* format_string, ...)
+ {
+ if (format_string == 0)
+ {
+ return *this;
+ }
+
+ va_list argList;
+ char* pbuf = 0;
+ va_start( argList, format_string );
+#ifdef _WIN32
+ int len = _vscprintf( format_string, argList );
+#else
+ int len = vsnprintf(nullptr, 0, format_string, argList);
+#endif
+ pbuf = new char[len + 1];
+ if (pbuf != 0)
+ {
+#ifdef _WIN32
+ vsprintf_s( pbuf, len + 1, format_string, argList );
+#else
+ vsprintf(pbuf, format_string, argList);
+#endif
+ *this = pbuf;
+ }
+ delete[] pbuf;
+ va_end( argList );
+
+ return *this;
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::trim_left
+ Access: public
+ Qualifier:
+ Parameter: value_type ch
+ Returns: string_ref&
+
+ Purpose: delete all char which is ch at the left of the string
+ *******************************************************************************/
+ string_ref& trim_left(value_type ch = ' ')
+ {
+ size_type off = this->find_first_not_of(ch);
+ if (off != string::npos)
+ {
+ this->erase(0, off);
+ }
+ return *this;
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::trim_right
+ Access: public
+ Qualifier:
+ Parameter: value_type ch
+ Returns: string_ref&
+
+ Purpose: delete all char which is ch at the right of the string
+ *******************************************************************************/
+ string_ref& trim_right(value_type ch = ' ')
+ {
+ size_type off = this->find_last_not_of(ch);
+ if (off == string::npos)
+ {
+ off = 0;
+ }
+ else
+ {
+ off++;
+ }
+ this->erase(off, length() - off);
+ return *this;
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::trim
+ Access: public
+ Qualifier:
+ Parameter: value_type ch
+ Returns: string_ref&
+
+ Purpose: delete all char which is ch at the left and right of the string
+ *******************************************************************************/
+ string_ref& trim(value_type ch = ' ')
+ {
+ trim_left(ch);
+ trim_right(ch);
+ return *this;
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::float_num
+ Access: public static
+ Qualifier:
+ Parameter: const string & str
+ Returns: double
+
+ Purpose: parse str to a float number
+ *******************************************************************************/
+ static double float_num(const string& str)
+ {
+ return atof(str.c_str());
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::float_num
+ Access: public static
+ Qualifier:
+ Returns: double
+
+ Purpose: parse this to a float number
+ *******************************************************************************/
+ double float_num() const
+ {
+ return float_num(*this);
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::compare_nocase
+ Access: public
+ Qualifier: const
+ Parameter: const string & str
+ Returns: int
+
+ Purpose: compare string no case
+ *******************************************************************************/
+ int compare_nocase(const string& str) const
+ {
+#ifdef _WIN32
+ return _stricmp(this->c_str(), str.c_str());
+#else
+ return strcasecmp(this->c_str(), str.c_str());
+#endif
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::compare_nocase
+ Access: public
+ Qualifier: const
+ Parameter: size_type index
+ Parameter: size_type length
+ Parameter: const string & str
+ Returns: int
+
+ Purpose: compare substring no case
+ *******************************************************************************/
+ int compare_nocase( size_type index, size_type length, const string &str ) const
+ {
+ string_ref temp = this->substr(index, length);
+ return temp.compare_nocase(str);
+ }
+
+ /*******************************************************************************
+ Function: hl_lib::string_ref::compare_nocase
+ Access: public
+ Qualifier: const
+ Parameter: size_type index
+ Parameter: size_type length
+ Parameter: const string & str
+ Parameter: size_type index2
+ Parameter: size_type length2
+ Returns: int
+
+ Purpose: compare two substring no case
+ *******************************************************************************/
+ int compare_nocase( size_type index, size_type length, const string &str, size_type index2, size_type length2) const
+ {
+ string_ref temp1 = this->substr(index, length);
+ string_ref temp2 = str.substr(index2, length2);
+ return temp1.compare_nocase(temp2);
+ }
+
+ };
+
+}
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.cpp
new file mode 100644
index 0000000000..6769f5112d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.cpp
@@ -0,0 +1,106 @@
+#include "ParentProcessWatcher.h"
+#include <boost/process.hpp>
+
+#ifdef _WIN32
+#include <boost/process/windows.hpp>
+#endif
+
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+
+#include "ProcessIoService.h"
+#include "SimpleTimer.h"
+
+
+using namespace boost::asio::ip;
+using namespace std;
+
+struct ParentProcessWatcher::ParentProcessWatcherData : std::enable_shared_from_this<ParentProcessWatcherData>
+{
+ std::unique_ptr<SimpleTimer<boost::posix_time::seconds>> timer;
+ lsp::Log& _log;
+ std::function<void()> on_exit;
+ lsp::ProcessIoService asio_io;
+ std::shared_ptr < boost::process::opstream> write_to_service;
+ std::shared_ptr< boost::process::ipstream > read_from_service;
+ int pid;
+ const int _poll_delay_secs /*= 10*/;
+ std::string command;
+ std::shared_ptr<boost::process::child> c;
+
+ ParentProcessWatcherData(lsp::Log& log, int _pid,
+ const std::function<void()>&& callback, uint32_t poll_delay_secs) :
+ _log(log), on_exit(callback), pid(_pid), _poll_delay_secs(poll_delay_secs)
+ {
+#ifdef _WIN32
+ command = "cmd /c \"tasklist /FI \"PID eq " + std::to_string(pid) + "\" | findstr " +
+ std::to_string(pid) + "\"";
+#else
+ command = "ps -p " + std::to_string(pid);
+#endif
+
+ }
+
+ void run()
+ {
+ write_to_service = std::make_shared<boost::process::opstream>();
+ read_from_service = std::make_shared<boost::process::ipstream>();
+
+// const uint32_t POLL_DELAY_SECS = _poll_delay_secs;
+ auto self(shared_from_this());
+ std::error_code ec;
+ namespace bp = boost::process;
+ c = std::make_shared<bp::child>(asio_io.getIOService(), command,
+ ec,
+#ifdef _WIN32
+ bp::windows::hide,
+#endif
+ bp::std_out > *read_from_service,
+ bp::std_in < *write_to_service,
+ bp::on_exit([self](int exit_code, const std::error_code& ec_in) {
+ // the tasklist command should return 0 (parent process exists) or 1 (parent process doesn't exist)
+ if (exit_code == 1)//
+ {
+ if (self->on_exit)
+ {
+
+ std::thread([=]()
+ {
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ self->on_exit();
+ }).detach();
+ }
+ }
+ else
+ {
+ if (exit_code > 1)
+ {
+ self->_log.log(lsp::Log::Level::WARNING, "The tasklist command: '" + self->command + "' returns " + std::to_string(exit_code));
+ }
+
+ self->timer = std::make_unique<SimpleTimer<boost::posix_time::seconds>>(self->_poll_delay_secs, [=]() {
+ self->run();
+ });
+ }
+
+ }));
+ if (ec)
+ {
+ // fail
+ _log.log(lsp::Log::Level::SEVERE, "Start parent process watcher failed.");
+ }
+ }
+};
+
+ParentProcessWatcher::ParentProcessWatcher(lsp::Log& log, int pid,
+ const std::function<void()>&& callback, uint32_t poll_delay_secs) : d_ptr(new ParentProcessWatcherData(log, pid, std::move(callback), poll_delay_secs))
+{
+ d_ptr->run();
+}
+
+ParentProcessWatcher::~ParentProcessWatcher()
+{
+ if (d_ptr->timer)
+ d_ptr->timer->Stop();
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.h b/graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.h
new file mode 100644
index 0000000000..fa84e4109a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ParentProcessWatcher.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/MessageIssue.h"
+#include <memory>
+
+class ParentProcessWatcher
+{
+public:
+ struct ParentProcessWatcherData;
+
+ ParentProcessWatcher(lsp::Log& log, int pid, const std::function<void()>&& callback, uint32_t poll_delay_secs = 10);
+
+ ~ParentProcessWatcher();
+
+ std::shared_ptr<ParentProcessWatcherData> d_ptr;
+};
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ProcessIoService.h b/graphics/asymptote/LspCpp/LibLsp/lsp/ProcessIoService.h
new file mode 100644
index 0000000000..1389a1d5b7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ProcessIoService.h
@@ -0,0 +1,48 @@
+#pragma once
+#include <boost/asio.hpp>
+#include <iostream>
+
+namespace lsp
+{
+ class ProcessIoService
+ {
+ public:
+ using IOService = boost::asio::io_service;
+ using Work = boost::asio::io_service::work;
+ using WorkPtr = std::unique_ptr<Work>;
+
+ ProcessIoService() {
+
+ work_ = std::unique_ptr<Work>(new Work(ioService_));
+ auto temp_thread_ = new std::thread([this]
+ {
+ ioService_.run();
+ });
+ thread_ = std::unique_ptr<std::thread>(temp_thread_);
+ }
+
+ ProcessIoService(const ProcessIoService&) = delete;
+ ProcessIoService& operator=(const ProcessIoService&) = delete;
+
+ boost::asio::io_service& getIOService()
+ {
+ return ioService_;
+ }
+
+ void stop()
+ {
+
+ work_.reset();
+
+ thread_->join();
+
+ }
+
+ private:
+ IOService ioService_;
+ WorkPtr work_;
+ std::unique_ptr<std::thread> thread_;
+
+ };
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.cpp
new file mode 100644
index 0000000000..90e3fcda08
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.cpp
@@ -0,0 +1,716 @@
+#include "ProtocolJsonHandler.h"
+#include "general/initialize.h"
+#include "general/shutdown.h"
+#include "textDocument/code_action.h"
+#include "textDocument/code_lens.h"
+#include "textDocument/completion.h"
+
+
+#include "textDocument/did_close.h"
+
+#include "textDocument/highlight.h"
+#include "textDocument/document_link.h"
+#include "textDocument/formatting.h"
+#include "textDocument/hover.h"
+#include "textDocument/implementation.h"
+#include "textDocument/range_formatting.h"
+#include "textDocument/references.h"
+#include "textDocument/rename.h"
+#include "textDocument/signature_help.h"
+#include "textDocument/type_definition.h"
+#include "workspace/symbol.h"
+#include "textDocument/typeHierarchy.h"
+#include "out_list.h"
+#include "extention/jdtls/codeActionResult.h"
+#include "textDocument/declaration_definition.h"
+#include "textDocument/resolveCompletionItem.h"
+#include "textDocument/resolveCodeLens.h"
+#include "textDocument/colorPresentation.h"
+#include "textDocument/foldingRange.h"
+#include "textDocument/prepareRename.h"
+#include "textDocument/resolveTypeHierarchy.h"
+#include "textDocument/callHierarchy.h"
+#include "textDocument/selectionRange.h"
+#include "extention/jdtls/classFileContents.h"
+#include "extention/jdtls/buildWorkspace.h"
+#include "extention/jdtls/listOverridableMethods.h"
+#include "extention/jdtls/addOverridableMethods.h"
+#include "extention/jdtls/checkHashCodeEqualsStatus.h"
+#include "extention/jdtls/checkConstructorsStatus.h"
+#include "extention/jdtls/checkDelegateMethodsStatus.h"
+#include "extention/jdtls/checkToStringStatus.h"
+#include "extention/jdtls/executeCommand.h"
+#include "extention/jdtls/findLinks.h"
+#include "extention/jdtls/generateAccessors.h"
+#include "extention/jdtls/generateConstructors.h"
+#include "extention/jdtls/generateDelegateMethods.h"
+#include "extention/jdtls/generateHashCodeEquals.h"
+#include "extention/jdtls/generateToString.h"
+#include "extention/jdtls/getMoveDestinations.h"
+#include "extention/jdtls/Move.h"
+#include "extention/jdtls/organizeImports.h"
+#include "general/exit.h"
+#include "general/initialized.h"
+#include "extention/jdtls/projectConfigurationUpdate.h"
+#include "textDocument/did_change.h"
+#include "textDocument/did_open.h"
+#include "textDocument/did_save.h"
+#include "textDocument/publishDiagnostics.h"
+#include "textDocument/willSave.h"
+
+#include "workspace/didChangeWorkspaceFolders.h"
+#include "workspace/did_change_configuration.h"
+#include "workspace/did_change_watched_files.h"
+#include "windows/MessageNotify.h"
+#include "language/language.h"
+#include "client/registerCapability.h"
+#include "client/unregisterCapability.h"
+#include "LibLsp/JsonRpc/Cancellation.h"
+#include "textDocument/didRenameFiles.h"
+#include "textDocument/semanticHighlighting.h"
+#include "workspace/configuration.h"
+
+
+void AddStadardResponseJsonRpcMethod(MessageJsonHandler& handler)
+{
+
+ handler.method2response[td_initialize::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if(visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_initialize::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_shutdown::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_shutdown::response::ReflectReader(visitor);
+ };
+ handler.method2response[td_codeAction::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_codeAction::response::ReflectReader(visitor);
+ };
+ handler.method2response[td_codeLens::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_codeLens::response::ReflectReader(visitor);
+ };
+ handler.method2response[td_completion::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_completion::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_definition::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_definition::response::ReflectReader(visitor);
+ };
+ handler.method2response[td_declaration::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_declaration::response::ReflectReader(visitor);
+ };
+ handler.method2response[td_willSaveWaitUntil::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_willSaveWaitUntil::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_highlight::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_highlight::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_links::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_links::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_linkResolve::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_linkResolve::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_symbol::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_symbol::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_formatting::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_formatting::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_hover::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_hover::response::ReflectReader(visitor);
+
+ };
+
+ handler.method2response[td_implementation::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_implementation::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_rangeFormatting::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_rangeFormatting::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_references::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_references::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_rename::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_rename::response::ReflectReader(visitor);
+ };
+
+
+ handler.method2response[td_signatureHelp::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_signatureHelp::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[td_typeDefinition::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_typeDefinition::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[wp_executeCommand::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return wp_executeCommand::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[wp_symbol::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return wp_symbol::response::ReflectReader(visitor);
+ };
+ handler.method2response[td_typeHierarchy::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_typeHierarchy::response::ReflectReader(visitor);
+ };
+ handler.method2response[completionItem_resolve::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return completionItem_resolve::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[codeLens_resolve::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return codeLens_resolve::response::ReflectReader(visitor);
+
+ };
+
+ handler.method2response[td_colorPresentation::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_colorPresentation::response::ReflectReader(visitor);
+
+ };
+ handler.method2response[td_documentColor::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_documentColor::response::ReflectReader(visitor);
+
+ };
+ handler.method2response[td_foldingRange::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_foldingRange::response::ReflectReader(visitor);
+
+ };
+ handler.method2response[td_prepareRename::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_prepareRename::response::ReflectReader(visitor);
+
+ };
+ handler.method2response[typeHierarchy_resolve::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return typeHierarchy_resolve::response::ReflectReader(visitor);
+
+ };
+
+ handler.method2response[td_selectionRange::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_selectionRange::response::ReflectReader(visitor);
+
+ };
+ handler.method2response[td_didRenameFiles::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_didRenameFiles::response::ReflectReader(visitor);
+
+ };
+ handler.method2response[td_willRenameFiles::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return td_willRenameFiles::response::ReflectReader(visitor);
+
+ };
+
+}
+
+
+void AddJavaExtentionResponseJsonRpcMethod(MessageJsonHandler& handler)
+{
+ handler.method2response[java_classFileContents::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_classFileContents::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_buildWorkspace::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_buildWorkspace::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_listOverridableMethods::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_listOverridableMethods::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_listOverridableMethods::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_listOverridableMethods::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_checkHashCodeEqualsStatus::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_checkHashCodeEqualsStatus::response::ReflectReader(visitor);
+ };
+
+
+ handler.method2response[java_addOverridableMethods::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_addOverridableMethods::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_checkConstructorsStatus::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_checkConstructorsStatus::response::ReflectReader(visitor);
+ };
+
+
+ handler.method2response[java_checkDelegateMethodsStatus::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_checkDelegateMethodsStatus::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_checkToStringStatus::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_checkToStringStatus::response::ReflectReader(visitor);
+ };
+
+
+ handler.method2response[java_generateAccessors::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_generateAccessors::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_generateConstructors::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_generateConstructors::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_generateDelegateMethods::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_generateDelegateMethods::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_generateHashCodeEquals::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_generateHashCodeEquals::response::ReflectReader(visitor);
+ };
+ handler.method2response[java_generateToString::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_generateToString::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_generateToString::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_generateToString::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_getMoveDestinations::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_getMoveDestinations::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_getRefactorEdit::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_getRefactorEdit::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_move::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_move::response ::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_organizeImports::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_organizeImports::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_resolveUnimplementedAccessors::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_resolveUnimplementedAccessors::response::ReflectReader(visitor);
+ };
+
+ handler.method2response[java_searchSymbols::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return java_searchSymbols::response::ReflectReader(visitor);
+ };
+
+ handler.method2request[WorkspaceConfiguration::request::kMethodInfo] = [](Reader& visitor)
+ {
+ return WorkspaceConfiguration::request::ReflectReader(visitor);
+ };
+ handler.method2request[WorkspaceFolders::request::kMethodInfo] = [](Reader& visitor)
+ {
+ return WorkspaceFolders::request::ReflectReader(visitor);
+ };
+
+}
+
+void AddNotifyJsonRpcMethod(MessageJsonHandler& handler)
+{
+
+ handler.method2notification[Notify_Exit::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_Exit::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[Notify_InitializedNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_InitializedNotification::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[java_projectConfigurationUpdate::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return java_projectConfigurationUpdate::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_TextDocumentDidChange::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_TextDocumentDidChange::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_TextDocumentDidClose::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_TextDocumentDidClose::notify::ReflectReader(visitor);
+ };
+
+
+ handler.method2notification[Notify_TextDocumentDidOpen::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_TextDocumentDidOpen::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_TextDocumentDidSave::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_TextDocumentDidSave::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_TextDocumentPublishDiagnostics::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_TextDocumentPublishDiagnostics::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[Notify_semanticHighlighting::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_semanticHighlighting::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[td_willSave::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return td_willSave::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_LogMessage::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_LogMessage::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[Notify_ShowMessage::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_ShowMessage::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[Notify_WorkspaceDidChangeWorkspaceFolders::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_WorkspaceDidChangeWorkspaceFolders::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_WorkspaceDidChangeConfiguration::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_WorkspaceDidChangeConfiguration::notify::ReflectReader(visitor);
+ };
+
+
+ handler.method2notification[Notify_WorkspaceDidChangeWatchedFiles::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_WorkspaceDidChangeWatchedFiles::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_sendNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_sendNotification::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[lang_status::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return lang_status::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[lang_actionableNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return lang_actionableNotification::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[lang_progressReport::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return lang_progressReport::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[lang_eventNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return lang_eventNotification::notify::ReflectReader(visitor);
+ };
+}
+
+void AddRequstJsonRpcMethod(MessageJsonHandler& handler)
+{
+ handler.method2request[Req_ClientRegisterCapability::request::kMethodInfo]= [](Reader& visitor)
+ {
+
+ return Req_ClientRegisterCapability::request::ReflectReader(visitor);
+ };
+ handler.method2request[Req_ClientUnregisterCapability::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return Req_ClientUnregisterCapability::request::ReflectReader(visitor);
+ };
+}
+
+void AddStandardRequestJsonRpcMethod(MessageJsonHandler& handler)
+{
+
+ handler.method2request[td_initialize::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_initialize::request::ReflectReader(visitor);
+ };
+ handler.method2request[td_shutdown::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_shutdown::request::ReflectReader(visitor);
+ };
+ handler.method2request[td_codeAction::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+
+ return td_codeAction::request::ReflectReader(visitor);
+ };
+ handler.method2request[td_codeLens::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_codeLens::request::ReflectReader(visitor);
+ };
+ handler.method2request[td_completion::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_completion::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_definition::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_definition::request::ReflectReader(visitor);
+ };
+ handler.method2request[td_declaration::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_declaration::request::ReflectReader(visitor);
+ };
+ handler.method2request[td_willSaveWaitUntil::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+ return td_willSaveWaitUntil::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_highlight::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_highlight::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_links::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_links::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_linkResolve::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_linkResolve::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_symbol::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_symbol::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_formatting::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_formatting::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_hover::request::kMethodInfo] = [](Reader& visitor)
+ {
+ return td_hover::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_implementation::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_implementation::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_didRenameFiles::request::kMethodInfo] = [](Reader& visitor)
+ {
+
+ return td_didRenameFiles::request::ReflectReader(visitor);
+ };
+
+ handler.method2request[td_willRenameFiles::request::kMethodInfo] = [](Reader& visitor)
+ {
+ return td_willRenameFiles::request::ReflectReader(visitor);
+ };
+}
+
+
+lsp::ProtocolJsonHandler::ProtocolJsonHandler()
+{
+ AddStadardResponseJsonRpcMethod(*this);
+ AddJavaExtentionResponseJsonRpcMethod(*this);
+ AddNotifyJsonRpcMethod(*this);
+ AddStandardRequestJsonRpcMethod(*this);
+ AddRequstJsonRpcMethod(*this);
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.h b/graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.h
new file mode 100644
index 0000000000..b563f810d2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ProtocolJsonHandler.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/MessageJsonHandler.h"
+namespace lsp {
+ class ProtocolJsonHandler : public MessageJsonHandler
+ {
+ public:
+ ProtocolJsonHandler();
+ };
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/ResourceOperation.h b/graphics/asymptote/LspCpp/LibLsp/lsp/ResourceOperation.h
new file mode 100644
index 0000000000..caf2ea5d5f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/ResourceOperation.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <vector>
+#include "lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/lsp/lsTextEdit.h"
+struct ResourceOperation {
+ std::string kind;
+ virtual ~ResourceOperation() = default;
+
+ MAKE_SWAP_METHOD(ResourceOperation, kind);
+};
+MAKE_REFLECT_STRUCT(ResourceOperation, kind);
+extern void Reflect(Writer& visitor, ResourceOperation* value);
+struct CreateFileOptions{
+
+ /**
+ * Overwrite existing file. Overwrite wins over `ignoreIfExists`
+ */
+ boost::optional<bool> overwrite = false;
+
+ /**
+ * Ignore if exists.
+ */
+ boost::optional< bool> ignoreIfExists =false;
+
+ MAKE_SWAP_METHOD(CreateFileOptions, overwrite, ignoreIfExists)
+};
+MAKE_REFLECT_STRUCT(CreateFileOptions, overwrite, ignoreIfExists)
+struct lsCreateFile :public ResourceOperation {
+
+ /**
+ * The resource to create.
+ */
+ lsCreateFile();
+ lsDocumentUri uri;
+
+ /**
+ * Additional options
+ */
+ boost::optional<CreateFileOptions> options;
+
+
+ /**
+ * An optional annotation identifer describing the operation.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<lsChangeAnnotationIdentifier> annotationId;
+
+ MAKE_SWAP_METHOD(lsCreateFile, kind, uri, options, annotationId)
+};
+MAKE_REFLECT_STRUCT(lsCreateFile, kind, uri,options, annotationId)
+
+
+struct DeleteFileOptions {
+ /**
+ * Delete the content recursively if a folder is denoted.
+ */
+ boost::optional<bool> recursive = false;
+
+ /**
+ * Ignore the operation if the file doesn't exist.
+ */
+ boost::optional<bool> ignoreIfNotExists = false;
+
+
+ MAKE_SWAP_METHOD(DeleteFileOptions, recursive, ignoreIfNotExists);
+};
+
+MAKE_REFLECT_STRUCT(DeleteFileOptions, recursive, ignoreIfNotExists)
+
+struct lsDeleteFile :public ResourceOperation {
+ /**
+ * The file to delete.
+ */
+ lsDeleteFile();
+ lsDocumentUri uri;
+
+ /**
+ * Delete options.
+ */
+ boost::optional<DeleteFileOptions> options;
+
+ MAKE_SWAP_METHOD(lsDeleteFile, kind, uri, options);
+};
+MAKE_REFLECT_STRUCT(lsDeleteFile, kind, uri,options);
+
+typedef CreateFileOptions RenameFileOptions;
+struct lsRenameFile :public ResourceOperation {
+ /**
+ * The old (existing) location.
+ */
+ lsRenameFile();
+ lsDocumentUri oldUri;
+
+ /**
+ * The new location.
+ */
+
+ lsDocumentUri newUri;
+
+ /**
+ * Rename options.
+ */
+ boost::optional<RenameFileOptions> options;
+
+ /**
+ * An optional annotation identifer describing the operation.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<lsChangeAnnotationIdentifier> annotationId;
+
+ MAKE_SWAP_METHOD(lsRenameFile, kind, oldUri, newUri, options, annotationId)
+};
+MAKE_REFLECT_STRUCT(lsRenameFile, kind, oldUri, newUri, options, annotationId);
+
+
+extern ResourceOperation* GetResourceOperation(lsp::Any& lspAny); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/SimpleTimer.h b/graphics/asymptote/LspCpp/LibLsp/lsp/SimpleTimer.h
new file mode 100644
index 0000000000..0a2707979d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/SimpleTimer.h
@@ -0,0 +1,49 @@
+#pragma once
+#include <thread>
+#include <atomic>
+#include <functional>
+#include <boost/asio.hpp>
+
+template<typename Duration = boost::posix_time::milliseconds>
+class SimpleTimer
+{
+public:
+ SimpleTimer(unsigned int duration,const std::function<void()>& _call_back)
+ :is_running_(true), call_back(_call_back), _deadline_timer(_ios, Duration(duration))
+ {
+ _deadline_timer.async_wait([&](const boost::system::error_code& e)
+ {
+ if (e.value() == boost::asio::error::operation_aborted)
+ {
+ return;
+ }
+ if(is_running_.load(std::memory_order_relaxed))
+ {
+ call_back();
+ }
+
+ });
+ _thread = std::thread([this] { _ios.run(); });
+ }
+ ~SimpleTimer()
+ {
+ Stop();
+ }
+ void Stop()
+ {
+ is_running_.store(false, std::memory_order_relaxed);
+ _ios.stop();
+ if (_thread.joinable())
+ {
+ _thread.join();
+ }
+ }
+private:
+ std::atomic_bool is_running_;
+ std::function<void()> call_back;
+ boost::asio::io_service _ios;
+ boost::asio::deadline_timer _deadline_timer;
+ std::thread _thread;
+
+
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/client/registerCapability.h b/graphics/asymptote/LspCpp/LibLsp/lsp/client/registerCapability.h
new file mode 100644
index 0000000000..fa5d111403
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/client/registerCapability.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+
+/**
+ * General parameters to register for a capability.
+ */
+
+struct Registration {
+ static Registration Create(const std::string& method);
+ /**
+ * The id used to register the request. The id can be used to deregister
+ * the request again.
+ */
+ std::string id;
+
+ /**
+ * The method / capability to register for.
+ */
+
+ std::string method;
+
+ MAKE_SWAP_METHOD(Registration, id, method);
+};
+
+
+MAKE_REFLECT_STRUCT(Registration, id, method);
+
+/**
+ * The client/registerCapability request is sent from the server to the client to register
+ * for a new capability on the client side. Not all clients need to support dynamic
+ * capability registration. A client opts in via the dynamicRegistration property on the
+ * specific client capabilities. A client can even provide dynamic registration for
+ * capability A but not for capability B (see TextDocumentClientCapabilities as an example).
+ */
+struct RegistrationParams
+{
+ std::vector<Registration> registrations;
+ MAKE_SWAP_METHOD(RegistrationParams, registrations);
+};
+/**
+ * The client/registerCapability request is sent from the server to the client
+ * to register for a new capability on the client side.
+ * Not all clients need to support dynamic capability registration.
+ * A client opts in via the ClientCapabilities.dynamicRegistration property
+ */
+MAKE_REFLECT_STRUCT(RegistrationParams, registrations);
+
+DEFINE_REQUEST_RESPONSE_TYPE(Req_ClientRegisterCapability, RegistrationParams,JsonNull, "client/registerCapability"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/client/unregisterCapability.h b/graphics/asymptote/LspCpp/LibLsp/lsp/client/unregisterCapability.h
new file mode 100644
index 0000000000..aa51d7efee
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/client/unregisterCapability.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "LibLsp/lsp/lsDocumentUri.h"
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+/**
+ * General parameters to unregister a capability.
+ */
+
+struct Unregistration {
+ /**
+ * The id used to unregister the request or notification. Usually an id
+ * provided during the register request.
+ */
+
+ std::string id;
+
+ /**
+ * The method / capability to unregister for.
+ */
+
+ std::string method;
+
+ MAKE_SWAP_METHOD(Unregistration, id, method);
+};
+MAKE_REFLECT_STRUCT(Unregistration, id, method);
+/**
+ * The client/unregisterCapability request is sent from the server to the client to unregister
+ * a previously registered capability.
+ */
+struct UnregistrationParams
+{
+ std::vector<Unregistration> unregisterations;
+ MAKE_SWAP_METHOD(UnregistrationParams, unregisterations);
+};
+
+MAKE_REFLECT_STRUCT(UnregistrationParams, unregisterations);
+
+DEFINE_REQUEST_RESPONSE_TYPE(Req_ClientUnregisterCapability, UnregistrationParams,JsonNull, "client/unregisterCapability"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/Move.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/Move.h
new file mode 100644
index 0000000000..c0beb625f2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/Move.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "getMoveDestinations.h"
+#include "getRefactorEdit.h"
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_move, MoveParams, RefactorWorkspaceEdit, "java/move");
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/OverridableMethod.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/OverridableMethod.h
new file mode 100644
index 0000000000..cfb17fdf34
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/OverridableMethod.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <string>
+struct OverridableMethod
+{
+ std::string bindingKey;
+ std::string name;
+ std::vector<std::string> parameters;
+ bool unimplemented = false;
+ std::string declaringClass;
+ std::string declaringClassType;
+
+ void swap(OverridableMethod& arg) noexcept
+ {
+ bindingKey.swap(arg.bindingKey);
+ name.swap(arg.name);
+ parameters.swap(arg.parameters);
+ declaringClass.swap(arg.declaringClass);
+ declaringClassType.swap(arg.declaringClassType);
+ std::swap(unimplemented, arg.unimplemented);
+ }
+};
+MAKE_REFLECT_STRUCT(OverridableMethod, bindingKey, name, parameters, unimplemented, declaringClass, declaringClassType);
+
+struct OverridableMethodsResponse
+{
+ std::string type;
+ std::vector<OverridableMethod> methods;
+
+ MAKE_SWAP_METHOD(OverridableMethodsResponse, type, methods)
+};
+
+MAKE_REFLECT_STRUCT(OverridableMethodsResponse, type, methods)
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h
new file mode 100644
index 0000000000..c7faa94d6c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <string>
+
+
+struct WorkspaceSymbolParams
+{
+ std::string query;
+ MAKE_SWAP_METHOD(WorkspaceSymbolParams, query);
+};
+MAKE_REFLECT_STRUCT(WorkspaceSymbolParams, query);
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/addOverridableMethods.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/addOverridableMethods.h
new file mode 100644
index 0000000000..5da14a452a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/addOverridableMethods.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/message.h"
+#include "OverridableMethod.h"
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+struct AddOverridableMethodParams {
+ lsCodeActionParams context;
+ std::vector<OverridableMethod> overridableMethods;
+
+ MAKE_SWAP_METHOD(AddOverridableMethodParams, context, overridableMethods);
+};
+
+MAKE_REFLECT_STRUCT(AddOverridableMethodParams, context, overridableMethods);
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_addOverridableMethods, AddOverridableMethodParams, lsWorkspaceEdit, "java/addOverridableMethods");
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/buildWorkspace.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/buildWorkspace.h
new file mode 100644
index 0000000000..a2c2c062cc
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/buildWorkspace.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "WorkspaceSymbolParams.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+
+
+
+
+enum class BuildWorkspaceStatus : uint8_t{
+
+ FAILED, SUCCEED, WITH_ERROR, CANCELLED,
+};
+MAKE_REFLECT_TYPE_PROXY(BuildWorkspaceStatus)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_buildWorkspace, bool, BuildWorkspaceStatus, "java/buildWorkspace"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h
new file mode 100644
index 0000000000..261a0cc551
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "checkHashCodeEqualsStatus.h"
+
+struct LspMethodBinding {
+ std::string bindingKey;
+ std::string name;
+ std::vector< std::string> parameters;
+
+ MAKE_SWAP_METHOD(LspMethodBinding, bindingKey, name, parameters);
+};
+MAKE_REFLECT_STRUCT(LspMethodBinding, bindingKey, name, parameters);
+
+
+struct CheckConstructorsResponse {
+ std::vector<LspMethodBinding> constructors;
+ std::vector<LspVariableBinding> fields;
+ MAKE_SWAP_METHOD(CheckConstructorsResponse, constructors, fields)
+};
+MAKE_REFLECT_STRUCT(CheckConstructorsResponse, constructors,fields)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_checkConstructorsStatus, lsCodeActionParams, CheckConstructorsResponse,"java/checkConstructorsStatus")
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h
new file mode 100644
index 0000000000..729639eafa
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "checkHashCodeEqualsStatus.h"
+#include "checkConstructorsStatus.h"
+
+struct LspDelegateField {
+ LspVariableBinding field;
+ std::vector<LspMethodBinding> delegateMethods;
+
+ MAKE_SWAP_METHOD(LspDelegateField, field, delegateMethods);
+};
+MAKE_REFLECT_STRUCT(LspDelegateField, field, delegateMethods);
+
+
+struct CheckDelegateMethodsResponse {
+ std::vector<LspDelegateField> delegateFields;
+
+ MAKE_SWAP_METHOD(CheckDelegateMethodsResponse, delegateFields)
+};
+MAKE_REFLECT_STRUCT(CheckDelegateMethodsResponse, delegateFields)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_checkDelegateMethodsStatus,
+ lsCodeActionParams, CheckDelegateMethodsResponse, "java/checkDelegateMethodsStatus");
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h
new file mode 100644
index 0000000000..1d9652dd44
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include <LibLsp/lsp/lsCodeAction.h>
+
+#include "LibLsp/lsp/CodeActionParams.h"
+
+struct LspVariableBinding {
+ std::string bindingKey;
+ std::string name;
+ std::string type;
+ bool isField;
+ void swap(LspVariableBinding& arg) noexcept
+ {
+ bindingKey.swap(arg.bindingKey);
+ name.swap(arg.name);
+ type.swap(arg.type);
+ std::swap(isField, arg.isField);
+ }
+};
+MAKE_REFLECT_STRUCT(LspVariableBinding, bindingKey, name, type, isField)
+
+struct CheckHashCodeEqualsResponse {
+ std::string type;
+ std::vector<LspVariableBinding> fields;
+ std::vector<std::string> existingMethods;
+ MAKE_SWAP_METHOD(CheckHashCodeEqualsResponse, type, fields, type, existingMethods)
+};
+MAKE_REFLECT_STRUCT(CheckHashCodeEqualsResponse, type, fields, type, existingMethods)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_checkHashCodeEqualsStatus,
+ lsCodeActionParams, CheckHashCodeEqualsResponse, "java/checkHashCodeEqualsStatus")
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkToStringStatus.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkToStringStatus.h
new file mode 100644
index 0000000000..24580d94c0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/checkToStringStatus.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "checkHashCodeEqualsStatus.h"
+struct CheckToStringResponse {
+ std::string type;
+ std::vector<LspVariableBinding> fields;
+ bool exists;
+ void swap(CheckToStringResponse& arg) noexcept
+ {
+ type.swap(arg.type);
+ fields.swap(arg.fields);
+ std::swap(exists, arg.exists);
+ }
+};
+MAKE_REFLECT_STRUCT(CheckToStringResponse,type,fields,exists)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_checkToStringStatus,
+ lsCodeActionParams, CheckToStringResponse ,"java/checkToStringStatus")
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/classFileContents.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/classFileContents.h
new file mode 100644
index 0000000000..70eb121b99
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/classFileContents.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include <string>
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_classFileContents, lsTextDocumentIdentifier, std::string ,"java/classFileContents");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/codeActionResult.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/codeActionResult.h
new file mode 100644
index 0000000000..02024e3d93
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/codeActionResult.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsCodeAction.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+#include <set>
+#include "LibLsp/lsp/textDocument/code_action.h"
+
+namespace SourceAssistProcessor {
+
+ /*std::set<std::string> UNSUPPORTED_RESOURCES = { "module-info.java", "package-info.java"
+ };*/
+
+// static const char* COMMAND_ID_ACTION_OVERRIDEMETHODSPROMPT = "java.action.overrideMethodsPrompt";
+// static const char* COMMAND_ID_ACTION_HASHCODEEQUALSPROMPT = "java.action.hashCodeEqualsPrompt";
+// static const char* COMMAND_ID_ACTION_ORGANIZEIMPORTS = "java.action.organizeImports";
+// static const char* COMMAND_ID_ACTION_GENERATETOSTRINGPROMPT = "java.action.generateToStringPrompt";
+// static const char* COMMAND_ID_ACTION_GENERATEACCESSORSPROMPT = "java.action.generateAccessorsPrompt";
+// static const char* COMMAND_ID_ACTION_GENERATECONSTRUCTORSPROMPT = "java.action.generateConstructorsPrompt";
+// static const char* COMMAND_ID_ACTION_GENERATEDELEGATEMETHODSPROMPT = "java.action.generateDelegateMethodsPrompt";
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/executeCommand.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/executeCommand.h
new file mode 100644
index 0000000000..92d4a3627b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/executeCommand.h
@@ -0,0 +1,29 @@
+#pragma once
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "LibLsp/lsp/lsWorkspaceEdit.h"
+#include "LibLsp/lsp/ExecuteCommandParams.h"
+namespace buildpath
+{
+// static const char* EDIT_ORGNIZEIMPORTS = "java.edit.organizeImports";
+// static const char* RESOLVE_SOURCE_ATTACHMENT = "java.project.resolveSourceAttachment";
+
+// static const char* UPDATE_SOURCE_ATTACHMENT = "java.project.updateSourceAttachment";
+
+// static const char* ADD_TO_SOURCEPATH = "java.project.addToSourcePath";
+
+// static const char* REMOVE_FROM_SOURCEPATH = "java.project.removeFromSourcePath";
+
+// static const char* LIST_SOURCEPATHS = "java.project.listSourcePaths";
+ struct Result {
+ bool status;
+ std::string message;
+ };
+
+
+
+}
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_executeCommand, ExecuteCommandParams, lsWorkspaceEdit, "java/executeCommand");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/findLinks.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/findLinks.h
new file mode 100644
index 0000000000..d184c675d8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/findLinks.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "getRefactorEdit.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+
+struct FindLinksParams {
+ // Supported link types: superImplementation
+ std::string type;
+ lsTextDocumentPositionParams position;
+
+ MAKE_SWAP_METHOD(FindLinksParams, type, position)
+};
+MAKE_REFLECT_STRUCT(FindLinksParams,type,position)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_findLinks, FindLinksParams,lsp::Any, "java/findLinks");
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateAccessors.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateAccessors.h
new file mode 100644
index 0000000000..200d840e94
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateAccessors.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "checkHashCodeEqualsStatus.h"
+#include "resolveUnimplementedAccessors.h"
+
+
+struct GenerateAccessorsParams {
+ lsCodeActionParams context;
+ std::vector<AccessorField> accessors;
+
+
+ MAKE_SWAP_METHOD(GenerateAccessorsParams, context, accessors)
+};
+MAKE_REFLECT_STRUCT(GenerateAccessorsParams, context, accessors)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_generateAccessors, GenerateAccessorsParams, lsWorkspaceEdit, "java/generateAccessors");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateConstructors.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateConstructors.h
new file mode 100644
index 0000000000..77c49a66a2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateConstructors.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "checkHashCodeEqualsStatus.h"
+#include "checkConstructorsStatus.h"
+
+
+struct GenerateConstructorsParams {
+ lsCodeActionParams context;
+ std::vector<LspMethodBinding> constructors;
+ std::vector< LspVariableBinding >fields;
+ MAKE_SWAP_METHOD(GenerateConstructorsParams, context, fields)
+};
+MAKE_REFLECT_STRUCT(GenerateConstructorsParams, context, fields)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_generateConstructors, GenerateConstructorsParams, lsWorkspaceEdit, "java/generateConstructors");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h
new file mode 100644
index 0000000000..8958ae4d7e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "checkHashCodeEqualsStatus.h"
+#include "checkConstructorsStatus.h"
+
+struct LspDelegateEntry {
+ LspVariableBinding field;
+ LspMethodBinding delegateMethod;
+ MAKE_SWAP_METHOD(LspDelegateEntry, field, delegateMethod);
+};
+MAKE_REFLECT_STRUCT(LspDelegateEntry, field, delegateMethod);
+
+
+struct GenerateDelegateMethodsParams {
+ lsCodeActionParams context;
+ std::vector<LspDelegateEntry> delegateEntries;
+ MAKE_SWAP_METHOD(GenerateDelegateMethodsParams, context, delegateEntries)
+};
+MAKE_REFLECT_STRUCT(GenerateDelegateMethodsParams, context, delegateEntries)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_generateDelegateMethods, GenerateDelegateMethodsParams, lsWorkspaceEdit, "java/generateDelegateMethods");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h
new file mode 100644
index 0000000000..937c358733
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <LibLsp/lsp/lsCodeAction.h>
+
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "checkHashCodeEqualsStatus.h"
+
+struct GenerateHashCodeEqualsParams {
+ lsCodeActionParams context;
+ std::vector<LspVariableBinding> fields;
+ bool regenerate= false;
+ void swap(GenerateHashCodeEqualsParams& arg) noexcept
+ {
+ context.swap(arg.context);
+ fields.swap(arg.fields);
+ std::swap(regenerate, arg.regenerate);
+ }
+};
+MAKE_REFLECT_STRUCT(GenerateHashCodeEqualsParams, context, fields, regenerate);
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_generateHashCodeEquals, GenerateHashCodeEqualsParams, lsWorkspaceEdit, "java/generateHashCodeEquals")
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateToString.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateToString.h
new file mode 100644
index 0000000000..1f8ccc73b8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/generateToString.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "checkHashCodeEqualsStatus.h"
+
+
+struct GenerateToStringParams {
+ lsCodeActionParams context;
+ std::vector< LspVariableBinding >fields;
+
+ MAKE_SWAP_METHOD(GenerateToStringParams, context, fields)
+
+};
+MAKE_REFLECT_STRUCT(GenerateToStringParams, context, fields)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_generateToString, GenerateToStringParams, lsWorkspaceEdit, "java/generateToString");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getMoveDestinations.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getMoveDestinations.h
new file mode 100644
index 0000000000..bcbf6f8c2b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getMoveDestinations.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/lsp/CodeActionParams.h"
+
+struct MoveKindInfo
+{
+ static std::string moveResource()
+ {
+ return "moveResource";
+ }
+ static std::string moveInstanceMethod()
+ {
+ return "moveInstanceMethod";
+ }
+ static std::string moveStaticMember()
+ {
+ return "moveStaticMember";
+ }
+};
+
+struct MoveParams {
+ /**
+ * The supported move kind: moveResource, moveInstanceMethod, moveStaticMember,
+ * moveTypeToNewFile.
+ */
+ std::string moveKind;
+ /**
+ * The selected resource uris when the move operation is triggered.
+ */
+ std::vector<std::string> sourceUris;
+ /**
+ * The code action params when the move operation is triggered.
+ */
+ boost::optional<lsCodeActionParams> params;
+ /**
+ * The possible destination: a folder/package, class, instanceDeclaration.
+ */
+ lsp::Any destination;
+ bool updateReferences;
+ void swap(MoveParams& arg) noexcept
+ {
+ moveKind.swap(arg.moveKind);
+ sourceUris.swap(arg.sourceUris);
+ params.swap(arg.params);
+ destination.swap(arg.destination);
+ std::swap(updateReferences, arg.updateReferences);
+ }
+};
+MAKE_REFLECT_STRUCT(MoveParams, moveKind, sourceUris, params, destination, updateReferences);
+
+struct MoveDestinationsResponse {
+ std::string errorMessage;
+ std::vector<lsp::Any > destinations;
+ MAKE_SWAP_METHOD(MoveDestinationsResponse, errorMessage, destinations);
+};
+MAKE_REFLECT_STRUCT(MoveDestinationsResponse, errorMessage, destinations);
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_getMoveDestinations, MoveParams, MoveDestinationsResponse, "java/getMoveDestinations");
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getRefactorEdit.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getRefactorEdit.h
new file mode 100644
index 0000000000..e46327075a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/getRefactorEdit.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+
+
+#include <string>
+#include <vector>
+#include "WorkspaceSymbolParams.h"
+#include "LibLsp/lsp/method_type.h"
+#include "LibLsp/lsp/textDocument/code_action.h"
+#include "LibLsp/lsp/lsFormattingOptions.h"
+
+namespace
+RefactorProposalUtility
+{
+ extern const char* APPLY_REFACTORING_COMMAND_ID;
+ extern const char* EXTRACT_VARIABLE_ALL_OCCURRENCE_COMMAND;
+ extern const char* EXTRACT_VARIABLE_COMMAND;
+ extern const char* EXTRACT_CONSTANT_COMMAND;
+ extern const char* EXTRACT_METHOD_COMMAND;
+ extern const char* EXTRACT_FIELD_COMMAND;
+ extern const char* CONVERT_VARIABLE_TO_FIELD_COMMAND;
+ extern const char* MOVE_FILE_COMMAND;
+ extern const char* MOVE_INSTANCE_METHOD_COMMAND;
+ extern const char* MOVE_STATIC_MEMBER_COMMAND;
+ extern const char* MOVE_TYPE_COMMAND;
+};
+
+
+struct RenamePosition {
+ lsDocumentUri uri;
+ int offset = 0;
+ int length = 0;
+ void swap(RenamePosition& arg) noexcept
+ {
+ uri.swap(arg.uri);
+ std::swap(offset, arg.offset);
+ std::swap(length, arg.length);
+ }
+};
+MAKE_REFLECT_STRUCT(RenamePosition, uri, offset, length);
+
+struct GetRefactorEditParams
+{
+ std::string command;
+ std::vector<lsp::Any> commandArguments;
+ lsCodeActionParams context;
+ boost::optional<lsFormattingOptions> options;
+ MAKE_SWAP_METHOD(GetRefactorEditParams, command, context, options);
+};
+MAKE_REFLECT_STRUCT(GetRefactorEditParams, command, context, options);
+
+
+
+
+struct RefactorWorkspaceEdit {
+ /**
+ * The workspace edit this code action performs.
+ */
+ lsWorkspaceEdit edit;
+ /**
+ * A command this code action executes. If a code action provides a edit and a
+ * command, first the edit is executed and then the command.
+ */
+
+ boost::optional<std::string> errorMessage;
+
+ boost::optional < lsCommandWithAny > command;
+
+ MAKE_SWAP_METHOD(RefactorWorkspaceEdit, edit, command, errorMessage)
+};
+MAKE_REFLECT_STRUCT(RefactorWorkspaceEdit,edit,command,errorMessage)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_getRefactorEdit, GetRefactorEditParams, RefactorWorkspaceEdit, "java/getRefactorEdit");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/listOverridableMethods.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/listOverridableMethods.h
new file mode 100644
index 0000000000..13b73ce5c2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/listOverridableMethods.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "OverridableMethod.h"
+
+
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_listOverridableMethods, lsCodeActionParams, OverridableMethodsResponse, "java/listOverridableMethods");
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/organizeImports.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/organizeImports.h
new file mode 100644
index 0000000000..817d52d32b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/organizeImports.h
@@ -0,0 +1,12 @@
+#pragma once
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <LibLsp/lsp/lsCodeAction.h>
+
+#include "LibLsp/lsp/CodeActionParams.h"
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_organizeImports, lsCodeActionParams, lsWorkspaceEdit, "java/organizeImports");
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h
new file mode 100644
index 0000000000..342d167093
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+
+#include <string>
+#include <vector>
+#include "WorkspaceSymbolParams.h"
+
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+DEFINE_NOTIFICATION_TYPE(java_projectConfigurationUpdate, lsTextDocumentIdentifier, "java/projectConfigurationUpdate");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h
new file mode 100644
index 0000000000..ba77041474
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "checkHashCodeEqualsStatus.h"
+
+
+struct AccessorField {
+ std::string fieldName;
+ bool isStatic =false;
+ bool generateGetter = false;
+ bool generateSetter = false;
+ void swap(AccessorField& arg) noexcept{
+ fieldName.swap(arg.fieldName);
+ std::swap(isStatic, arg.isStatic);
+ std::swap(generateGetter, arg.generateGetter);
+ std::swap(generateSetter, arg.generateSetter);
+ }
+};
+
+MAKE_REFLECT_STRUCT(AccessorField, fieldName,isStatic,generateGetter,generateSetter)
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_resolveUnimplementedAccessors, lsCodeActionParams, std::vector<AccessorField>, "java/resolveUnimplementedAccessors");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/searchSymbols.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/searchSymbols.h
new file mode 100644
index 0000000000..ac8a2419f6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/jdtls/searchSymbols.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+
+#include <string>
+#include <vector>
+#include "WorkspaceSymbolParams.h"
+#include "LibLsp/lsp/method_type.h"
+#include "LibLsp/lsp/symbol.h"
+
+
+struct SearchSymbolParams :public WorkspaceSymbolParams
+{
+ boost::optional<std::string> projectName;
+ boost::optional< bool >sourceOnly;
+ boost::optional< int> maxResults;
+ MAKE_SWAP_METHOD(SearchSymbolParams, query, projectName, sourceOnly, maxResults);
+};
+MAKE_REFLECT_STRUCT(SearchSymbolParams, query, projectName, sourceOnly, maxResults);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(java_searchSymbols, SearchSymbolParams, std::vector<lsSymbolInformation>, "java/searchSymbols");
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/SCTConfig.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/SCTConfig.h
new file mode 100644
index 0000000000..7b41118c0a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/SCTConfig.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <string>
+#include <vector>
+#include <LibLsp/JsonRpc/serializer.h>
+using namespace std;
+
+
+struct TCP_option
+{
+ std::string host = "127.0.0.1";
+ int port = 8889;
+
+};
+MAKE_REFLECT_STRUCT(TCP_option,host,port)
+
+
+struct SCTConfig
+{
+ static SCTConfig* newInstance(const string& file_path,string& error);
+ std::string version;
+ std::string file_name;
+
+ boost::optional<bool> start_by_jcide;
+
+ boost::optional<TCP_option> tcp;
+ boost::optional<vector<string>> args;
+
+ // internal using
+ bool broken = false;
+ std::string error;
+};
+
+
+MAKE_REFLECT_STRUCT(SCTConfig, version,file_name, tcp, args, start_by_jcide);
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/protocol.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/protocol.h
new file mode 100644
index 0000000000..1f227a6110
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/protocol.h
@@ -0,0 +1,222 @@
+#pragma once
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+struct DownLoadCapFileParams
+{
+ lsDocumentUri uri;
+ MAKE_SWAP_METHOD(DownLoadCapFileParams, uri);
+};
+MAKE_REFLECT_STRUCT(DownLoadCapFileParams, uri);
+
+struct NormalActionResult
+{
+ bool state = false;
+ boost::optional<std::vector<uint8_t>> data;
+ boost::optional<std::string> info;
+ MAKE_SWAP_METHOD(NormalActionResult, state, data, info);
+};
+MAKE_REFLECT_STRUCT(NormalActionResult, data, state, info)
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_DownLoadCapFile, DownLoadCapFileParams, NormalActionResult, "sct/download_cap");
+
+
+
+
+enum class SctProtocol :uint8_t
+{
+ T01 = 0, T0 = 1, T1 = 2,
+};
+MAKE_REFLECT_TYPE_PROXY(SctProtocol);
+
+struct ConnectParams
+{
+
+ SctProtocol protocol= SctProtocol::T01;
+ boost::optional<std::string> reader;
+ boost::optional<lsp::Any> data;
+ MAKE_SWAP_METHOD(ConnectParams, reader, protocol,data);
+};
+MAKE_REFLECT_STRUCT(ConnectParams, reader, protocol, data);
+DEFINE_REQUEST_RESPONSE_TYPE(sct_Connect, ConnectParams, NormalActionResult, "sct/connect");
+
+
+
+struct SetProtocolParams
+{
+
+ SctProtocol protocol = SctProtocol::T01;
+
+};
+MAKE_REFLECT_STRUCT(SetProtocolParams, protocol);
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_SetProtocol, SetProtocolParams, NormalActionResult, "sct/set_protocol");
+
+struct GPAuthParams
+{
+ boost::optional < std::string> scp;
+ boost::optional < std::string > key;
+ boost::optional < lsp::Any > option;
+ MAKE_SWAP_METHOD(GPAuthParams, key, scp, option);
+};
+MAKE_REFLECT_STRUCT(GPAuthParams, key, scp, option);
+DEFINE_REQUEST_RESPONSE_TYPE(sct_gp_auth, GPAuthParams, NormalActionResult ,"sct/gp_auth");
+
+
+
+struct InstallAppletParams
+{
+ std::vector<uint8_t> package_aid;
+ std::vector<uint8_t> applet_aid;
+ boost::optional < std::vector<uint8_t>> instance_aid;
+ boost::optional<std::vector<uint8_t>> authority;
+ boost::optional<std::vector<uint8_t>> parameters;
+ MAKE_SWAP_METHOD(InstallAppletParams, package_aid, applet_aid, instance_aid, authority, parameters);
+};
+MAKE_REFLECT_STRUCT(InstallAppletParams, package_aid, applet_aid, instance_aid, authority, parameters);
+DEFINE_REQUEST_RESPONSE_TYPE(sct_InstalllApplet, InstallAppletParams, NormalActionResult, "sct/install_applet");
+
+
+struct TransmitParams
+{
+ std::vector<unsigned char> command;
+ MAKE_SWAP_METHOD(TransmitParams, command);
+};
+MAKE_REFLECT_STRUCT(TransmitParams, command);
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_Transmit, TransmitParams, NormalActionResult,"sct/transmit");
+
+DEFINE_NOTIFICATION_TYPE(sct_Disconnect,JsonNull, "sct/disconnect")
+
+
+struct SetWindowPosParams{
+ int X = 0;
+ int Y = 0;
+ int cx = 100;
+ int cy = 100;
+
+ MAKE_SWAP_METHOD(SetWindowPosParams, X, Y, cx, cy);
+};
+MAKE_REFLECT_STRUCT(SetWindowPosParams, X, Y, cx, cy);
+DEFINE_NOTIFICATION_TYPE(sct_SetWindowsPos, SetWindowPosParams, "sct/set_windows_pos")
+
+struct SetWindowVisibleParams
+{
+ static const int HIDE = 0;
+ static const int MINSIZE = 1;
+ static const int MAXSIZE = 2;
+ static const int NORMAL = 3;
+ int state = NORMAL;
+ MAKE_SWAP_METHOD(SetWindowVisibleParams, state);
+};
+MAKE_REFLECT_STRUCT(SetWindowVisibleParams, state);
+DEFINE_NOTIFICATION_TYPE(sct_SetWindowsVisible, SetWindowVisibleParams, "sct/set_windows_visible")
+
+
+
+enum CardInfoType:uint32_t
+{
+ ATR_TYPE = 0,
+ ATS_TYPE = 1,
+};
+MAKE_REFLECT_TYPE_PROXY(CardInfoType);
+
+
+struct GetCardInfoParams
+{
+ CardInfoType type_;
+};
+MAKE_REFLECT_STRUCT(GetCardInfoParams, type_);
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_GetCardInfo, GetCardInfoParams, NormalActionResult, "sct/get_card_info");
+
+
+struct JdwpInfo
+{
+ std::string host="127.0.0.1";
+ uint32_t jdwp_port = 9075;
+
+};
+
+MAKE_REFLECT_STRUCT(JdwpInfo, host, jdwp_port);
+
+struct LaunchResult
+{
+ bool state;
+ boost::optional<JdwpInfo> info;
+ boost::optional<std::string> error;
+ MAKE_SWAP_METHOD(LaunchResult, state, info, error);
+};
+MAKE_REFLECT_STRUCT(LaunchResult, state, info, error);
+
+
+struct JcvmOutputParams
+{
+ std::string data;
+ MAKE_SWAP_METHOD(JcvmOutputParams, data);
+};
+MAKE_REFLECT_STRUCT(JcvmOutputParams, data);
+
+DEFINE_NOTIFICATION_TYPE(sct_NotifyJcvmOutput, JcvmOutputParams,"sct/notify_jcvm_output");
+
+
+struct LaunchParam
+{
+ enum
+ {
+ LAUNCH_FOR_DEBUG = 0,
+ LAUNCH_FOR_RUN = 1
+ };
+ boost::optional<uint32_t> launch_for_what;
+
+};
+MAKE_REFLECT_STRUCT(LaunchParam, launch_for_what);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_Launch, LaunchParam, LaunchResult , "sct/launch");
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_CheckBeforeLaunch, JsonNull, NormalActionResult, "sct/check_before_launch");
+
+
+
+DEFINE_NOTIFICATION_TYPE(sct_NotifyDisconnect, JsonNull,"sct/notify_disconnect");
+
+
+DEFINE_NOTIFICATION_TYPE(sct_TerminateLaunch, JsonNull, "sct/terminate_launch");
+
+
+
+
+struct sctInitializeParams {
+ // The process Id of the parent process that started
+ // the server. Is null if the process has not been started by another process.
+ // If the parent process is not alive then the server should exit (see exit
+ // notification) its process.
+ boost::optional<int> processId;
+
+ // User provided initialization options.
+ boost::optional<lsp::Any> initializationOptions;
+ boost::optional<int> version;
+
+};
+MAKE_REFLECT_STRUCT(sctInitializeParams,processId,initializationOptions, version);
+
+struct sctServerCapabilities {
+ bool gp_auth = false;
+ bool gp_key = false;
+ boost::optional<int> version;
+ MAKE_SWAP_METHOD(sctServerCapabilities, gp_auth, gp_key, version);
+};
+MAKE_REFLECT_STRUCT(sctServerCapabilities, gp_auth, gp_key, version);
+
+
+struct stcInitializeResult
+{
+ sctServerCapabilities capabilities;
+};
+MAKE_REFLECT_STRUCT(stcInitializeResult, capabilities);
+
+DEFINE_REQUEST_RESPONSE_TYPE(sct_initialize, sctInitializeParams, stcInitializeResult, "sct/initialize");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.cpp
new file mode 100644
index 0000000000..25c21ecddc
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.cpp
@@ -0,0 +1,743 @@
+
+#include <deque>
+#include "sct.h"
+#include "SCTConfig.h"
+#include <rapidjson/document.h>
+#include <rapidjson/istreamwrapper.h>
+#include <fstream>
+#include <boost/filesystem.hpp>
+#include "LibLsp/lsp/general/exit.h"
+#include "LibLsp/lsp/general/initialized.h"
+#include "LibLsp/lsp/windows/MessageNotify.h"
+#include "LibLsp/lsp/language/language.h"
+#include "LibLsp/JsonRpc/Condition.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+#include "LibLsp/JsonRpc/json.h"
+
+namespace lsp {
+ class Log;
+}
+
+using namespace std;
+using lsp::Log;
+
+
+//
+//MethodType sct_DownLoadCapFile::request::kMethodInfo = "sct/download_cap";
+//
+//MethodType sct_Transmit::request::kMethodInfo = "sct/transmit";
+//
+//MethodType sct_Connect::request::kMethodInfo = "sct/connect";
+//
+//MethodType sct_Disconnect::request::kMethodInfo = "sct/disconnect";
+//
+//MethodType sct_InstalllApplet::request::kMethodInfo = "sct/install_applet";
+//
+//MethodType sct_gp_auth::request::kMethodInfo = "sct/gp_auth";
+//
+//MethodType sct_SetWindowsPos::request::kMethodInfo = "sct/set_windows_pos";
+//
+//MethodType sct_SetWindowsVisible::request::kMethodInfo = "sct/set_windows_visible";
+//
+//
+//MethodType sct_NotifyJcvmOutput::request::kMethodInfo = "sct/notify_jcvm_output";
+//
+//MethodType sct_Launch::request::kMethodInfo = "sct/launch";
+//
+//MethodType sct_SetProtocol::request::kMethodInfo = "sct/set_protocol";
+//
+//MethodType sct_CheckBeforeLaunch::request::kMethodInfo = "sct/check_before_launch";
+//
+//MethodType sct_GetCardInfo::request::kMethodInfo = "sct/get_card_info";
+//
+//MethodType sct_NotifyDisconnect::request::kMethodInfo = "sct/notify_disconnect";
+//MethodType sct_TerminateLaunch::request::kMethodInfo = "sct/terminate_launch";
+//MethodType sct_initialize::request::kMethodInfo = "sct/initialize";
+
+
+ SCTConfig* SCTConfig::newInstance(const string& file_path, string& error)
+{
+ if(!boost::filesystem::exists(file_path))
+ {
+ error = "file no exists.";
+ return nullptr;
+ }
+ using namespace rapidjson;
+ using namespace std;
+ std::unique_ptr<SCTConfig> sct = std::make_unique<SCTConfig>();
+ try
+ {
+ std::wifstream ifs(file_path);
+ WIStreamWrapper isw(ifs);
+
+ Document d;
+ d.ParseStream(isw);
+ if(!d.HasParseError())
+ {
+ JsonReader reader{ &d };
+ Reflect(reader, *sct.get());
+ }
+ }
+ catch (std::exception& e)
+ {
+ string temp = "Reflect failed. exception info:";
+
+ temp += e.what();
+ error = temp;
+ sct.get()->broken = true;
+ sct.get()->error = temp;
+ }
+ return sct.release();
+}
+
+
+SmartCardTool::SmartCardTool(): m_jdwpPort(0), m_curProtocol(SctProtocol::T01), log(nullptr)
+{
+ m_ipAddr = "127.0.0.1";
+}
+
+void AddNotifyJsonRpcMethod(sct::ProtocolJsonHandler& handler)
+{
+ handler.method2notification[Notify_Exit::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_Exit::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[Notify_InitializedNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_InitializedNotification::notify::ReflectReader(visitor);
+ };
+
+
+ handler.method2notification[Notify_LogMessage::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_LogMessage::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[Notify_ShowMessage::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_ShowMessage::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[Notify_sendNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return Notify_sendNotification::notify::ReflectReader(visitor);
+ };
+
+ handler.method2notification[lang_actionableNotification::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return lang_actionableNotification::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[lang_progressReport::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return lang_progressReport::notify::ReflectReader(visitor);
+ };
+
+
+ handler.method2notification[sct_NotifyJcvmOutput::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return sct_NotifyJcvmOutput::notify::ReflectReader(visitor);
+ };
+ handler.method2notification[sct_NotifyDisconnect::notify::kMethodInfo] = [](Reader& visitor)
+ {
+ return sct_NotifyDisconnect::notify::ReflectReader(visitor);
+ };
+
+}
+
+sct::ProtocolJsonHandler::ProtocolJsonHandler()
+{
+ AddNotifyJsonRpcMethod(*this);
+
+ method2response[sct_DownLoadCapFile::request::kMethodInfo ] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_DownLoadCapFile::response::ReflectReader(visitor);
+ };
+ method2response[sct_Connect::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_Connect::response::ReflectReader(visitor);
+ };
+ method2response[sct_SetProtocol::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_SetProtocol::response::ReflectReader(visitor);
+ };
+ method2response[sct_gp_auth::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_gp_auth::response::ReflectReader(visitor);
+ };
+ method2response[sct_InstalllApplet::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_InstalllApplet::response::ReflectReader(visitor);
+ };
+ method2response[sct_Transmit::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_Transmit::response::ReflectReader(visitor);
+ };
+
+ method2response[sct_GetCardInfo::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_GetCardInfo::response::ReflectReader(visitor);
+ };
+
+ method2response[sct_Launch::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_Launch::response::ReflectReader(visitor);
+ };
+ method2response[sct_CheckBeforeLaunch::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_CheckBeforeLaunch::response::ReflectReader(visitor);
+ };
+
+
+ method2response[sct_initialize::request::kMethodInfo] = [](Reader& visitor)
+ {
+ if (visitor.HasMember("error"))
+ return Rsp_Error::ReflectReader(visitor);
+
+ return sct_initialize::response::ReflectReader(visitor);
+ };
+
+}
+bool SmartCardTool::check_sct_alive()
+{
+ if (sct)
+ {
+ return true;
+ }
+ if(log)
+ {
+ wstring strPrompt = L"sct is not alvie.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+}
+
+bool SmartCardTool::initialize(int processId, int version)
+{
+
+ if(!check_sct_alive())
+ {
+ return false;
+ }
+ sct_initialize::request request;
+ request.params.processId = processId;
+ request.params.version = version;
+
+ auto msg = sct->waitResponse(request, 100000);
+
+ if (!msg)
+ {
+ return false;
+ }
+
+ if (msg->is_error)
+ {
+ auto error = &msg->error;
+ log->error( error->error.ToString());
+ return false;
+ }
+ auto result = &msg->response;
+ _lsServerCapabilities.swap(result->result.capabilities);
+ return true;
+}
+
+
+
+SmartCardTool::~SmartCardTool()
+{
+
+
+}
+
+bool SmartCardTool::GetCardInfo(CardInfoType type_, std::vector<unsigned char>& out)
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_GetCardInfo::request request;
+ request.params.type_ = type_;
+
+ auto data = sct->waitResponse(request, 40000);
+
+ if (!data)
+ {
+ if (log)
+ {
+ wstring strPrompt = L"GetCardInfo request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ if (log)
+ {
+ string strPrompt = "GetCardInfo request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ out.swap(rsp->result.data.value());
+ return true;
+ }
+
+ if (log)
+ {
+ string strPrompt = "GetCardInfo failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+}
+
+
+
+bool SmartCardTool::Launch(bool for_debug)
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_Launch::request request;
+ if(for_debug)
+ {
+ request.params.launch_for_what = LaunchParam::LAUNCH_FOR_DEBUG;
+ }
+ else
+ {
+ request.params.launch_for_what = LaunchParam::LAUNCH_FOR_RUN;
+ }
+ auto data = sct->waitResponse(request, 100000);
+
+ if (!data)
+ {
+ if (log)
+ {
+ wstring strPrompt = L"Launch request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ if (log)
+ {
+ string strPrompt = "Launch request error." + data->error.ToJson();
+
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ if (log)
+ {
+ log->log(Log::Level::INFO, L"Launch successfully");
+ }
+ if(rsp->result.info)
+ {
+ m_ipAddr.swap(rsp->result.info.value().host);
+ m_jdwpPort = rsp->result.info.value().jdwp_port;
+
+ }
+ }
+ else
+ {
+ if (log)
+ {
+ string strPrompt = "Launch failed. Reason:";
+ strPrompt += rsp->result.error.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+ return false;
+ }
+ return true;
+}
+
+void SmartCardTool::TerminateLaunch()
+{
+ if (!check_sct_alive())
+ {
+ return ;
+ }
+ sct_TerminateLaunch::notify notify;
+ sct->send(notify);
+ connect_state = false;
+ return ;
+}
+
+void SmartCardTool::show_message(lsMessageType type_,
+ const std::string& msg)
+{
+ if (!check_sct_alive())
+ {
+ return ;
+ }
+ Notify_ShowMessage::notify notify;
+ notify.params.type = type_;
+ notify.params.message = msg;
+ sct->send(notify);
+}
+
+bool SmartCardTool::CheckBeforeLaunch()
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_CheckBeforeLaunch::request request;
+ auto data = sct->waitResponse(request, 50000);
+
+ if (!data)
+ {
+ wstring strPrompt = L"CheckBeforeLaunch request timeout.";
+ if(log)
+ {
+ log->log(Log::Level::SEVERE, strPrompt);
+ }
+
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ string strPrompt = "CheckBeforeLaunch request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ return true;
+ }
+
+
+ string strPrompt = "Check Before Launch JCVM failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+
+}
+
+
+bool SmartCardTool::Connect(SctProtocol protocol)
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_Connect::request request;
+
+ request.params.protocol = protocol;
+
+ auto data = sct->waitResponse(request, 40000);
+
+ if (!data)
+ {
+ wstring strPrompt = L"Connect request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ string strPrompt = "Connect request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp =&data->response;
+ if (rsp->result.state)
+ {
+ connect_state = true;
+ return true;
+ }
+ else
+ {
+ string strPrompt = "Connect failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+}
+
+
+
+
+void SmartCardTool::DisConnect()
+{
+ if (!check_sct_alive())
+ {
+ return ;
+ }
+ sct_Disconnect::notify notify;
+ sct->send(notify);
+ connect_state = false;
+ return ;
+}
+
+bool SmartCardTool::DownLoadCapFile(const string& strCapFileName)
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_DownLoadCapFile::request request;
+ request.params.uri.raw_uri_ = make_file_scheme_uri(strCapFileName);
+
+ auto data = sct->waitResponse(request, 40000);
+
+ if(!data)
+ {
+ wstring strPrompt = L"DownLoadCapFile request timeout.";
+ log->log(Log::Level::SEVERE,strPrompt);
+ return false;
+ }
+
+ if(data->is_error)
+ {
+ string strPrompt = "DownLoadCapFile request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp = &data->response;
+ if(rsp->result.state)
+ {
+ string strPrompt = "DownLoadCapFile successfully";
+ if(rsp->result.info)
+ {
+ strPrompt = rsp->result.info.value();
+ }
+ log->log(Log::Level::INFO, strPrompt);
+ return true;
+ }
+ else
+ {
+ string strPrompt = "DownLoadCapFile failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+}
+
+void SmartCardTool::SetWindowsVisible(SetWindowVisibleParams& params)
+{
+ if (!check_sct_alive())
+ {
+ return ;
+ }
+ sct_SetWindowsVisible::notify notify;
+ notify.params.swap(params);
+ sct->send(notify);
+
+}
+
+void SmartCardTool::SetWindowPos(SetWindowPosParams& params)
+{
+ sct_SetWindowsPos::notify notify;
+ notify.params.swap(params);
+ sct->send(notify);
+}
+
+bool SmartCardTool::SetProtocol(SctProtocol protocol)
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_SetProtocol::request request;
+
+ request.params.protocol = protocol;
+
+ auto data = sct->waitResponse(request, 40000);
+
+ if (!data)
+ {
+ wstring strPrompt = L"SetProtocol request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ string strPrompt = "SetProtocol request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ m_curProtocol = protocol;
+ return true;
+ }
+ else
+ {
+ string strPrompt = "SetProtocol failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+}
+
+bool SmartCardTool::GpAuth()
+{
+
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_gp_auth::request request;
+
+ auto data = sct->waitResponse(request, 100000);
+
+ if (!data)
+ {
+ wstring strPrompt = L"gp_auth request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ string strPrompt = "gp_auth request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ string strPrompt = "gp_auth request successfully.";
+ if (rsp->result.info)
+ strPrompt = rsp->result.info.value();
+
+ log->log(Log::Level::INFO, strPrompt);
+ return true;
+ }
+ else
+ {
+ string strPrompt = "gp_auth failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+}
+
+bool SmartCardTool::InstallApplet(InstallAppletParams& params)
+{
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_InstalllApplet::request request;
+ request.params.swap(params);
+ auto data = sct->waitResponse(request);
+
+ if (!data)
+ {
+ wstring strPrompt = L"Install Applet request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ string strPrompt = "Install Applet request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ string strPrompt = "Install Applet successfully.";
+ if (rsp->result.info)
+ strPrompt = rsp->result.info.value();
+ log->log(Log::Level::INFO, strPrompt);
+ return true;
+ }
+ else
+ {
+ string strPrompt = "Install Applet failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+}
+
+
+bool SmartCardTool::Transmit(const std::vector<unsigned char>& cmdApdu, std::vector<unsigned char>& rspApdu)
+{
+
+ if (!check_sct_alive())
+ {
+ return false;
+ }
+ sct_Transmit::request request;
+ request.params.command = cmdApdu;
+
+ auto data = sct->waitResponse(request);
+
+ if (!data)
+ {
+ wstring strPrompt = L"Transmit request timeout.";
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+ if (data->is_error)
+ {
+ string strPrompt = "Transmit request error." + data->error.ToJson();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+ auto rsp = &data->response;
+ if (rsp->result.state)
+ {
+ rspApdu.swap(rsp->result.data.value());
+ //log->log(Log::Level::INFO, L"Transmit successfully");
+ return true;
+ }
+ else
+ {
+ string strPrompt = "Transmit failed. Reason:";
+ strPrompt += rsp->result.info.value();
+ log->log(Log::Level::SEVERE, strPrompt);
+ return false;
+ }
+
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.h
new file mode 100644
index 0000000000..59ffe02fd7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sct/sct.h
@@ -0,0 +1,103 @@
+#pragma once
+
+#include <LibLsp/JsonRpc/RemoteEndPoint.h>
+#include <LibLsp/JsonRpc/Endpoint.h>
+#include <LibLsp/lsp/ProtocolJsonHandler.h>
+#include "protocol.h"
+enum class lsMessageType;
+enum CardInfoType : unsigned;
+enum class SctProtocol : unsigned char;
+struct InstallAppletParams;
+
+
+using namespace std;
+
+class ModeState;
+namespace sct
+{
+ class ProtocolJsonHandler : public MessageJsonHandler
+ {
+ public:
+ ProtocolJsonHandler();
+ };
+
+}
+class SmartCardTool
+{
+ //IP �����ֽ���
+ std::string m_ipAddr;
+ volatile uint16_t m_jdwpPort;
+
+
+ SctProtocol m_curProtocol;
+public:
+ enum JCIDE_VERSION
+ {
+ V5_KIND = 5
+ };
+ SmartCardTool();
+ ~SmartCardTool();
+
+
+ bool GetCardInfo(CardInfoType type_,std::vector<unsigned char>&);
+ bool Launch(bool for_debug = false);
+
+ void TerminateLaunch();
+ void show_message(lsMessageType type_,const std::string& msg);
+ bool CheckBeforeLaunch();
+
+ string GetIpAddr(){return m_ipAddr;}
+
+ uint16_t GetJdwpPort(){return m_jdwpPort;}
+
+
+
+ void SetWindowsVisible(SetWindowVisibleParams&);
+ void SetWindowPos(SetWindowPosParams&);
+
+ SctProtocol GetProtocol(){return m_curProtocol;}
+
+
+ bool SetProtocol(SctProtocol protocol = SctProtocol::T01);
+
+ bool GpAuth();
+
+
+ bool InstallApplet(InstallAppletParams&);;
+
+ bool DownLoadCapFile(const string& strCapFileName);
+
+
+
+ bool IsConnected() const {
+
+ return connect_state;
+ }
+
+ string GetErrorString() { return {}; };
+
+ bool Connect(SctProtocol protocol = SctProtocol::T01);
+
+ void DisConnect();
+
+
+
+
+ bool Transmit(const std::vector<unsigned char>& cmdApdu, std::vector<unsigned char>& rspApdu) ;
+
+
+ lsp::Log* log;
+ volatile bool connect_state = false;
+
+ std::shared_ptr<RemoteEndPoint> sct;
+
+
+ bool initialize(int processId,int version);
+ const sctServerCapabilities& getServerCapabilities()const
+ {
+ return _lsServerCapabilities;
+ }
+private:
+ sctServerCapabilities _lsServerCapabilities;
+ bool check_sct_alive();
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sonarlint/protocol.h b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sonarlint/protocol.h
new file mode 100644
index 0000000000..d81c3eaa63
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/extention/sonarlint/protocol.h
@@ -0,0 +1,176 @@
+#pragma once
+#include <string>
+#include <boost/optional.hpp>
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/lsp/general/InitializeParams.h"
+
+struct LintRule
+{
+ std::string key;
+ std::string name;
+
+
+ std::string Display() const
+ {
+ return name + " (" + key + ")";
+ }
+ bool activeByDefault = true;
+ boost::optional<std::string> severity;
+ boost::optional<std::string> type;
+ int icon_index = -1;
+ MAKE_SWAP_METHOD(LintRule, key, name, activeByDefault, severity, type);
+
+};
+MAKE_REFLECT_STRUCT(LintRule, key, name, activeByDefault, severity, type);
+
+
+struct RuleParameter {
+ std::string name;
+ boost::optional<std::string> description;
+ boost::optional<std::string> defaultValue;
+
+};
+MAKE_REFLECT_STRUCT(RuleParameter, name, description, defaultValue);
+
+struct ShowRuleDescriptionParams {
+
+ boost::optional<std::string> key;
+
+ boost::optional<std::string> name;
+
+ boost::optional<std::string> htmlDescription;
+
+ boost::optional<std::string> type;
+
+ boost::optional<std::string> severity;
+
+ boost::optional< std::vector<RuleParameter> > parameters;
+ MAKE_SWAP_METHOD(ShowRuleDescriptionParams, key, name, htmlDescription, type, severity, parameters)
+
+
+};
+MAKE_REFLECT_STRUCT(ShowRuleDescriptionParams, key, name, htmlDescription, type, severity, parameters);
+
+
+struct GetJavaConfigResponse {
+ std::string projectRoot;
+ std::string sourceLevel;
+ std::vector<std::string> classpath;
+ bool isTest;
+ std::string vmLocation;
+ MAKE_SWAP_METHOD(GetJavaConfigResponse, projectRoot, sourceLevel, classpath, isTest, vmLocation);
+};
+MAKE_REFLECT_STRUCT(GetJavaConfigResponse, projectRoot, sourceLevel, classpath, isTest, vmLocation);
+
+struct SetTraceNotificationParams {
+ lsInitializeParams::lsTrace value;
+};
+MAKE_REFLECT_STRUCT(SetTraceNotificationParams, value);
+
+
+struct ServerConnectionSettings {
+
+ std::string SONARCLOUD_URL = "https://sonarcloud.io";
+ std::vector<std::string>SONARCLOUD_ALIAS = { "https://sonarqube.com",
+ "https://www.sonarqube.com",
+ "https://www.sonarcloud.io",
+ "https://sonarcloud.io" };
+
+ std::string connectionId;
+ std::string serverUrl;
+ std::string token;
+ boost::optional<std::string> organizationKey;
+ MAKE_SWAP_METHOD(ServerConnectionSettings, connectionId, serverUrl, token, organizationKey)
+
+};
+MAKE_REFLECT_STRUCT(ServerConnectionSettings, connectionId, serverUrl, token, organizationKey)
+
+struct RuleSetting
+{
+ bool IsOn();
+ std::string level = "on";
+ RuleSetting(bool activate);
+ RuleSetting() = default;
+ void toggle();
+ void on()
+ {
+ level = "on";
+ }
+ void off()
+ {
+ level = "off";
+ }
+ void turn(bool activate)
+ {
+ if (activate)
+ {
+ on();
+ }
+ else
+ {
+ off();
+ }
+ }
+ boost::optional< std::map<std::string, std::string > > parameters;
+};
+MAKE_REFLECT_STRUCT(RuleSetting, level, parameters)
+
+struct ConsoleParams
+{
+ boost::optional < bool >showAnalyzerLogs;
+ boost::optional < bool >showVerboseLogs;
+ MAKE_SWAP_METHOD(ConsoleParams, showAnalyzerLogs, showVerboseLogs)
+};
+MAKE_REFLECT_STRUCT(ConsoleParams, showAnalyzerLogs, showVerboseLogs)
+
+struct SonarLintWorkspaceSettings
+{
+ boost::optional < bool > disableTelemetry;
+ boost::optional < std::map<std::string, ServerConnectionSettings> >connectedMode;
+ boost::optional<std::map<std::string, RuleSetting>> rules;
+ boost::optional<ConsoleParams> output;
+
+ boost::optional<std::string > pathToNodeExecutable;
+
+ boost::optional< std::map<std::string, std::string > > getConfigurationParameters(const std::string& ruleKey);
+
+
+};
+
+MAKE_REFLECT_STRUCT(SonarLintWorkspaceSettings, disableTelemetry, connectedMode,
+ rules, output, pathToNodeExecutable)
+
+
+
+ DEFINE_REQUEST_RESPONSE_TYPE(slls_listAllRules, JsonNull, lsp::Any, "sonarlint/listAllRules");
+
+
+
+DEFINE_NOTIFICATION_TYPE(Notify_didClasspathUpdate, lsDocumentUri, "sonarlint/didClasspathUpdate")
+
+
+DEFINE_NOTIFICATION_TYPE(Notify_didJavaServerModeChange, std::string, "sonarlint/didJavaServerModeChange")
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(slls_showSonarLintOutput, JsonNull, JsonNull, "sonarlint/showSonarLintOutput");
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(slls_openJavaHomeSettings, JsonNull, JsonNull, "sonarlint/openJavaHomeSettings");
+
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(slls_openPathToNodeSettings, JsonNull, JsonNull, "sonarlint/openPathToNodeSettings");
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(slls_showRuleDescription, ShowRuleDescriptionParams, JsonNull, "sonarlint/showRuleDescription");
+
+DEFINE_REQUEST_RESPONSE_TYPE(slls_getJavaConfig, lsDocumentUri, GetJavaConfigResponse, "sonarlint/getJavaConfig");
+
+
+DEFINE_NOTIFICATION_TYPE(slls_setTraceNotification, SetTraceNotificationParams, "$/setTraceNotification") \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/InitializeParams.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/InitializeParams.h
new file mode 100644
index 0000000000..f10080ea21
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/InitializeParams.h
@@ -0,0 +1,128 @@
+#pragma once
+
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "lsClientCapabilities.h"
+#include "LibLsp/lsp/workspace/workspaceFolders.h"
+
+struct ClientInfo {
+ std::string name;
+ boost::optional<std::string> version;
+
+ MAKE_SWAP_METHOD(ClientInfo,name,version);
+};
+MAKE_REFLECT_STRUCT(ClientInfo,name,version);
+
+struct lsInitializeParams {
+ // The process Id of the parent process that started
+ // the server. Is null if the process has not been started by another process.
+ // If the parent process is not alive then the server should exit (see exit
+ // notification) its process.
+ boost::optional<int> processId;
+
+ /**
+ * Information about the client
+ *
+ * @since 3.15.0
+ */
+ boost::optional<ClientInfo> clientInfo;
+ /**
+ * The locale the client is currently showing the user interface
+ * in. This must not necessarily be the locale of the operating
+ * system.
+ *
+ * Uses IETF language tags as the value's syntax
+ * (See https://en.wikipedia.org/wiki/IETF_language_tag)
+ *
+ * @since 3.16.0
+ */
+ boost::optional<std::string> locale;
+
+ // The rootPath of the workspace. Is null
+ // if no folder is open.
+ //
+ // @deprecated in favour of rootUri.
+ boost::optional<std::string> rootPath;
+
+ // The rootUri of the workspace. Is null if no
+ // folder is open. If both `rootPath` and `rootUri` are set
+ // `rootUri` wins.
+ boost::optional<lsDocumentUri> rootUri;
+
+ // User provided initialization options.
+ boost::optional<lsp::Any> initializationOptions;
+
+ // The capabilities provided by the client (editor or tool)
+ lsClientCapabilities capabilities;
+
+
+ /**
+ * An boost::optional extension to the protocol.
+ * To tell the server what client (editor) is talking to it.
+ */
+ // @Deprecated
+ boost::optional< std::string >clientName;
+
+
+
+ enum class lsTrace {
+ // NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose';
+ Off, // off
+ Messages, // messages
+ Verbose // verbose
+
+ };
+
+ // The initial trace setting. If omitted trace is disabled ('off').
+ lsTrace trace = lsTrace::Off;
+
+
+ /**
+ * The workspace folders configured in the client when the server starts.
+ * This property is only available if the client supports workspace folders.
+ * It can be `null` if the client supports workspace folders but none are
+ * configured.
+ *
+ * Since 3.6.0
+ */
+ boost::optional< std::vector<WorkspaceFolder> > workspaceFolders;
+
+ MAKE_SWAP_METHOD(lsInitializeParams,
+ processId,
+ rootPath,
+ rootUri,
+ initializationOptions,
+ capabilities, clientName, clientInfo,
+ trace, workspaceFolders, locale)
+};
+
+void Reflect(Reader& reader, lsInitializeParams::lsTrace& value);
+
+
+void Reflect(Writer& writer, lsInitializeParams::lsTrace& value);
+
+
+MAKE_REFLECT_STRUCT(lsInitializeParams,
+ processId,
+ rootPath,
+ rootUri,
+ initializationOptions,
+ capabilities, clientName, clientInfo,
+ trace, workspaceFolders, locale)
+
+struct lsInitializeError {
+ // Indicates whether the client should retry to send the
+ // initilize request after showing the message provided
+ // in the ResponseError.
+ bool retry;
+ void swap(lsInitializeError& arg) noexcept
+ {
+ auto tem = retry;
+ retry = arg.retry;
+ arg.retry = tem;
+ }
+};
+MAKE_REFLECT_STRUCT(lsInitializeError, retry);
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/exit.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/exit.h
new file mode 100644
index 0000000000..02fe216017
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/exit.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+/**
+ * A notification to ask the server to exit its process.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_Exit, boost::optional<JsonNull>, "exit");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.cpp
new file mode 100644
index 0000000000..4886be9b46
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.cpp
@@ -0,0 +1,45 @@
+#include "initialize.h"
+#include "LibLsp/JsonRpc/json.h"
+
+void Reflect(Reader& reader, lsInitializeParams::lsTrace& value)
+{
+ if (!reader.IsString())
+ {
+ value = lsInitializeParams::lsTrace::Off;
+ return;
+ }
+ std::string v = reader.GetString();
+ if (v == "off")
+ value = lsInitializeParams::lsTrace::Off;
+ else if (v == "messages")
+ value = lsInitializeParams::lsTrace::Messages;
+ else if (v == "verbose")
+ value = lsInitializeParams::lsTrace::Verbose;
+}
+
+void Reflect(Writer& writer, lsInitializeParams::lsTrace& value)
+{
+ switch (value)
+ {
+ case lsInitializeParams::lsTrace::Off:
+ writer.String("off");
+ break;
+ case lsInitializeParams::lsTrace::Messages:
+ writer.String("messages");
+ break;
+ case lsInitializeParams::lsTrace::Verbose:
+ writer.String("verbose");
+ break;
+ }
+}
+ void Reflect(Reader& visitor, std::pair<boost::optional<lsTextDocumentSyncKind>, boost::optional<lsTextDocumentSyncOptions> >& value)
+{
+ if(((JsonReader&)visitor).m_->IsObject())
+ {
+ Reflect(visitor, value.second);
+ }
+ else
+ {
+ Reflect(visitor, value.first);
+ }
+} \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.h
new file mode 100644
index 0000000000..eb8810939a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialize.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "LibLsp/JsonRpc/message.h"
+#include "InitializeParams.h"
+#include "lsServerCapabilities.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+
+
+
+
+
+
+/**
+ * The capabilities the language server provides.
+ */
+ struct InitializeResult {
+ lsServerCapabilities capabilities;
+ MAKE_SWAP_METHOD(InitializeResult, capabilities);
+ };
+
+MAKE_REFLECT_STRUCT(InitializeResult, capabilities);
+
+
+/**
+ * The initialize request is sent as the first request from the client to
+ * the server.
+ *
+ * If the server receives request or notification before the initialize request it should act as follows:
+ * - for a request the respond should be errored with code: -32001. The message can be picked by the server.
+ * - notifications should be dropped, except for the exit notification. This will allow the exit a server without an initialize request.
+ *
+ * Until the server has responded to the initialize request with an InitializeResult
+ * the client must not sent any additional requests or notifications to the server.
+ *
+ * During the initialize request the server is allowed to sent the notifications window/showMessage,
+ * window/logMessage and telemetry/event as well as the window/showMessageRequest request to the client.
+ */
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_initialize, lsInitializeParams, InitializeResult, "initialize");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialized.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialized.h
new file mode 100644
index 0000000000..bb6d12511c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/initialized.h
@@ -0,0 +1,13 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+/**
+ * The initialized notification is sent from the client to the server after
+ * the client received the result of the initialize request but before the
+ * client is sending any other request or notification to the server. The
+ * server can use the initialized notification for example to dynamically
+ * register capabilities.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_InitializedNotification, JsonNull, "initialized");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsClientCapabilities.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsClientCapabilities.h
new file mode 100644
index 0000000000..fcf6634e13
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsClientCapabilities.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "LibLsp/lsp/lsAny.h"
+#include "lsWorkspaceClientCapabilites.h"
+#include "lsTextDocumentClientCapabilities.h"
+
+/**
+ * Client capabilities specific to the used markdown parser.
+ *
+ * @since 3.16.0
+ */
+struct MarkdownClientCapabilities {
+ /**
+ * The name of the parser.
+ */
+ std::string parser;
+
+ /**
+ * The version of the parser.
+ */
+ boost::optional<std::string> version;
+ MAKE_SWAP_METHOD(MarkdownClientCapabilities, parser, version)
+
+};
+MAKE_REFLECT_STRUCT(MarkdownClientCapabilities, parser, version)
+
+struct lsClientCapabilities {
+ // Workspace specific client capabilities.
+ boost::optional<lsWorkspaceClientCapabilites> workspace;
+
+ // Text document specific client capabilities.
+ boost::optional<lsTextDocumentClientCapabilities> textDocument;
+
+ /**
+ * Window specific client capabilities.
+ */
+ boost::optional<lsp::Any> window;
+ /**
+ * Experimental client capabilities.
+ */
+ boost::optional<lsp::Any> experimental;
+
+ MAKE_SWAP_METHOD(lsClientCapabilities, workspace, textDocument, window, experimental)
+};
+MAKE_REFLECT_STRUCT(lsClientCapabilities, workspace, textDocument, window, experimental)
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsServerCapabilities.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsServerCapabilities.h
new file mode 100644
index 0000000000..66af2ced6b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsServerCapabilities.h
@@ -0,0 +1,589 @@
+#pragma once
+#include "LibLsp/lsp/method_type.h"
+
+
+#include <stdexcept>
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "InitializeParams.h"
+#include "LibLsp/lsp/textDocument/SemanticTokens.h"
+
+
+extern void Reflect(Reader&, std::pair<boost::optional<lsTextDocumentSyncKind>, boost::optional<lsTextDocumentSyncOptions> >&);
+
+//
+ // Code Action options.
+ //
+struct CodeActionOptions : WorkDoneProgressOptions {
+ //
+ // CodeActionKinds that this server may return.
+ //
+ // The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
+ // may list out every specific kind they provide.
+ //
+ typedef std::string CodeActionKind;
+ std::vector<CodeActionKind> codeActionKinds;
+
+ MAKE_SWAP_METHOD(CodeActionOptions, workDoneProgress, codeActionKinds);
+};
+MAKE_REFLECT_STRUCT(CodeActionOptions, workDoneProgress, codeActionKinds)
+struct CodeLensOptions : WorkDoneProgressOptions {
+ //
+ // Code lens has a resolve provider as well.
+ //
+ boost::optional<bool> resolveProvider ;
+ MAKE_SWAP_METHOD(CodeLensOptions, workDoneProgress, resolveProvider);
+};
+MAKE_REFLECT_STRUCT(CodeLensOptions, workDoneProgress, resolveProvider)
+
+
+// Format document on type options
+struct lsDocumentOnTypeFormattingOptions :WorkDoneProgressOptions {
+ // A character on which formatting should be triggered, like `}`.
+ std::string firstTriggerCharacter;
+
+ // More trigger characters.
+ std::vector<std::string> moreTriggerCharacter;
+ MAKE_SWAP_METHOD(lsDocumentOnTypeFormattingOptions, workDoneProgress,
+ firstTriggerCharacter,
+ moreTriggerCharacter);
+};
+MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, workDoneProgress,
+ firstTriggerCharacter,
+ moreTriggerCharacter);
+struct RenameOptions : WorkDoneProgressOptions {
+ //
+ // Renames should be checked and tested before being executed.
+ //
+ boost::optional<bool> prepareProvider;
+ MAKE_SWAP_METHOD(RenameOptions, workDoneProgress, prepareProvider);
+};
+MAKE_REFLECT_STRUCT(RenameOptions,workDoneProgress,prepareProvider)
+
+struct DocumentFilter{
+ //
+ // A language id, like `typescript`.
+ //
+ boost::optional<std::string> language;
+ //
+ // A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
+ //
+ boost::optional<std::string>scheme;
+ //
+ // A glob pattern, like `*.{ts,js}`.
+ //
+ // Glob patterns can have the following syntax:
+ // - `*` to match one or more characters in a path segment
+ // - `?` to match on one character in a path segment
+ // - `**` to match any number of path segments, including none
+ // - `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}
+ // matches all TypeScript and JavaScript files)
+ // - `[]` to declare a range of characters to match in a path segment
+ // (e.g., `example.[0-9]` to match on `example.0`, `example.1`,...)
+ // - `[!...]` to negate a range of characters to match in a path segment
+ // (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+ // not `example.0`)
+ //
+ boost::optional<std::string>pattern;
+ MAKE_SWAP_METHOD(DocumentFilter, language, scheme, pattern)
+};
+MAKE_REFLECT_STRUCT(DocumentFilter, language, scheme, pattern)
+
+//A document selector is the combination of one or more document filters.
+using DocumentSelector = std::vector<DocumentFilter>;
+
+// Document link options
+struct lsDocumentLinkOptions :WorkDoneProgressOptions {
+ // Document links have a resolve provider as well.
+ boost::optional<bool> resolveProvider;
+ MAKE_SWAP_METHOD(lsDocumentLinkOptions, workDoneProgress, resolveProvider);
+};
+MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, workDoneProgress,resolveProvider);
+
+// Execute command options.
+struct lsExecuteCommandOptions : WorkDoneProgressOptions {
+ // The commands to be executed on the server
+ std::vector<std::string> commands;
+ MAKE_SWAP_METHOD(lsExecuteCommandOptions, workDoneProgress, commands);
+};
+MAKE_REFLECT_STRUCT(lsExecuteCommandOptions, workDoneProgress, commands);
+
+
+struct TextDocumentRegistrationOptions
+{
+//
+ // A document selector to identify the scope of the registration. If set to null
+ // the document selector provided on the client side will be used.
+ //
+ boost::optional<DocumentSelector> documentSelector;
+
+ MAKE_SWAP_METHOD(TextDocumentRegistrationOptions, documentSelector);
+};
+MAKE_REFLECT_STRUCT(TextDocumentRegistrationOptions, documentSelector);
+
+//
+ // Static registration options to be returned in the initialize request.
+ //
+struct StaticRegistrationOptions :public TextDocumentRegistrationOptions
+{
+ //
+ // The id used to register the request. The id can be used to deregister
+ // the request again. See also Registration#id.
+ //
+ boost::optional<std::string> id;
+ MAKE_SWAP_METHOD(StaticRegistrationOptions, documentSelector, id)
+};
+MAKE_REFLECT_STRUCT(StaticRegistrationOptions, documentSelector,id)
+
+//
+ // The server supports workspace folder.
+ //
+ // Since 3.6.0
+ //
+
+struct WorkspaceFoldersOptions {
+ //
+ // The server has support for workspace folders
+ //
+ boost::optional<bool> supported;
+
+ //
+ // Whether the server wants to receive workspace folder
+ // change notifications.
+ //
+ // If a string is provided, the string is treated as an ID
+ // under which the notification is registered on the client
+ // side. The ID can be used to unregister for these events
+ // using the `client/unregisterCapability` request.
+ //
+ boost::optional<std::pair< boost::optional<std::string>, boost::optional<bool> > > changeNotifications;
+ MAKE_SWAP_METHOD(WorkspaceFoldersOptions, supported, changeNotifications);
+};
+MAKE_REFLECT_STRUCT(WorkspaceFoldersOptions, supported, changeNotifications);
+
+//
+ // A pattern kind describing if a glob pattern matches a file a folder or
+ // both.
+ //
+ // @since 3.16.0
+ //
+enum lsFileOperationPatternKind
+{
+ file,
+ folder
+};
+MAKE_REFLECT_TYPE_PROXY(lsFileOperationPatternKind)
+
+//
+ // Matching options for the file operation pattern.
+ //
+ // @since 3.16.0
+ //
+struct lsFileOperationPatternOptions {
+
+ //
+ // The pattern should be matched ignoring casing.
+ //
+ boost::optional<bool> ignoreCase;
+ MAKE_SWAP_METHOD(lsFileOperationPatternOptions, ignoreCase)
+};
+MAKE_REFLECT_STRUCT(lsFileOperationPatternOptions, ignoreCase)
+//
+ // A pattern to describe in which file operation requests or notifications
+ // the server is interested in.
+ //
+ // @since 3.16.0
+ //
+struct lsFileOperationPattern {
+ //
+ // The glob pattern to match. Glob patterns can have the following syntax:
+ // - `*` to match one or more characters in a path segment
+ // - `?` to match on one character in a path segment
+ // - `**` to match any number of path segments, including none
+ // - `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}`
+ // matches all TypeScript and JavaScript files)
+ // - `[]` to declare a range of characters to match in a path segment
+ // (e.g., `example.[0-9]` to match on `example.0`, `example.1`,...)
+ // - `[!...]` to negate a range of characters to match in a path segment
+ // (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+ // not `example.0`)
+ //
+ std::string glob;
+
+ //
+ // Whether to match files or folders with this pattern.
+ //
+ // Matches both if undefined.
+ //
+ boost::optional<lsFileOperationPatternKind> matches;
+
+ //
+ // Additional options used during matching.
+ //
+ boost::optional<lsFileOperationPatternOptions> options ;
+ MAKE_SWAP_METHOD(lsFileOperationPattern, glob, matches, options)
+};
+MAKE_REFLECT_STRUCT(lsFileOperationPattern, glob, matches, options)
+//
+ // A filter to describe in which file operation requests or notifications
+ // the server is interested in.
+ //
+ // @since 3.16.0
+ //
+struct lsFileOperationFilter {
+
+ //
+ // A Uri like `file` or `untitled`.
+ //
+ boost::optional<std::string> scheme;
+
+ //
+ // The actual file operation pattern.
+ //
+ boost::optional<lsFileOperationPattern> pattern;
+ MAKE_SWAP_METHOD(lsFileOperationFilter, scheme, pattern)
+};
+MAKE_REFLECT_STRUCT(lsFileOperationFilter, scheme, pattern)
+//
+ // The options to register for file operations.
+ //
+ // @since 3.16.0
+ //
+struct lsFileOperationRegistrationOptions {
+ //
+ // The actual filters.
+ //
+ boost::optional<std::vector<lsFileOperationFilter>> filters;
+ MAKE_SWAP_METHOD(lsFileOperationRegistrationOptions, filters)
+};
+MAKE_REFLECT_STRUCT(lsFileOperationRegistrationOptions, filters)
+
+struct WorkspaceServerCapabilities {
+ //
+ // The server supports workspace folder.
+ //
+ // Since 3.6.0
+ //
+ WorkspaceFoldersOptions workspaceFolders;
+
+
+ //
+ // The server is interested in file notifications/requests.
+ //
+ // @since 3.16.0
+ //
+ struct lsFileOperations
+ {
+ //
+ // The server is interested in receiving didCreateFiles
+ // notifications.
+ //
+ boost::optional<lsFileOperationRegistrationOptions> didCreate;
+
+ //
+ // The server is interested in receiving willCreateFiles requests.
+ //
+ boost::optional<lsFileOperationRegistrationOptions> willCreate;
+
+ //
+ // The server is interested in receiving didRenameFiles
+ // notifications.
+ //
+ boost::optional<lsFileOperationRegistrationOptions> didRename;
+
+ //
+ // The server is interested in receiving willRenameFiles requests.
+ //
+ boost::optional<lsFileOperationRegistrationOptions> willRename;
+
+ //
+ // The server is interested in receiving didDeleteFiles file
+ // notifications.
+ //
+ boost::optional<lsFileOperationRegistrationOptions> didDelete;
+
+ //
+ // The server is interested in receiving willDeleteFiles file
+ // requests.
+ //
+ boost::optional<lsFileOperationRegistrationOptions> willDelete;
+ MAKE_SWAP_METHOD(lsFileOperations, didCreate, willCreate, didRename, willRename, didDelete, willDelete)
+ };
+ boost::optional<lsFileOperations>fileOperations;
+
+
+ MAKE_SWAP_METHOD(WorkspaceServerCapabilities, workspaceFolders, fileOperations)
+};
+MAKE_REFLECT_STRUCT(WorkspaceServerCapabilities, workspaceFolders, fileOperations)
+MAKE_REFLECT_STRUCT(WorkspaceServerCapabilities::lsFileOperations, didCreate, willCreate, didRename, willRename, didDelete, willDelete)
+
+//
+ // Semantic highlighting server capabilities.
+ //
+ // <p>
+ // <b>Note:</b> the <a href=
+ // "https://github.com/Microsoft/vscode-languageserver-node/pull/367">{@code textDocument/semanticHighlighting}
+ // language feature</a> is not yet part of the official LSP specification.
+ //
+
+struct SemanticHighlightingServerCapabilities {
+ //
+ // A "lookup table" of semantic highlighting <a href="https://manual.macromates.com/en/language_grammars">TextMate scopes</a>
+ // supported by the language server. If not defined or empty, then the server does not support the semantic highlighting
+ // feature. Otherwise, clients should reuse this "lookup table" when receiving semantic highlighting notifications from
+ // the server.
+ //
+ std::vector< std::vector<std::string> > scopes;
+ MAKE_SWAP_METHOD(SemanticHighlightingServerCapabilities, scopes)
+};
+MAKE_REFLECT_STRUCT(SemanticHighlightingServerCapabilities, scopes)
+
+struct SemanticTokensServerFull
+{
+ //
+ // The server supports deltas for full documents.
+ //
+ bool delta =false;
+ MAKE_SWAP_METHOD(SemanticTokensServerFull, delta)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensServerFull, delta)
+struct SemanticTokensWithRegistrationOptions
+{
+ SemanticTokensLegend legend;
+
+ //
+ // Server supports providing semantic tokens for a specific range
+ // of a document.
+ //
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<lsp::Any> > > range;
+
+ //
+ // Server supports providing semantic tokens for a full document.
+ //
+ boost::optional< std::pair< boost::optional<bool>,
+ boost::optional<SemanticTokensServerFull> > > full;
+
+ //
+ // A document selector to identify the scope of the registration. If set to null
+ // the document selector provided on the client side will be used.
+ //
+ boost::optional < std::vector<DocumentFilter> > documentSelector;
+ //
+ // The id used to register the request. The id can be used to deregister
+ // the request again. See also Registration#id.
+ //
+ boost::optional<std::string> id;
+ MAKE_SWAP_METHOD(SemanticTokensWithRegistrationOptions, legend, range, full, documentSelector, id)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensWithRegistrationOptions, legend, range, full, documentSelector ,id)
+
+using DocumentColorOptions = WorkDoneProgressOptions;
+using FoldingRangeOptions = WorkDoneProgressOptions;
+struct lsServerCapabilities {
+ // Defines how text documents are synced. Is either a detailed structure
+ // defining each notification or for backwards compatibility the
+
+ // TextDocumentSyncKind number.
+ boost::optional< std::pair<boost::optional<lsTextDocumentSyncKind>,
+ boost::optional<lsTextDocumentSyncOptions> >> textDocumentSync;
+
+ // The server provides hover support.
+ boost::optional<bool> hoverProvider;
+
+ // The server provides completion support.
+ boost::optional < lsCompletionOptions > completionProvider;
+
+ // The server provides signature help support.
+ boost::optional < lsSignatureHelpOptions > signatureHelpProvider;
+
+ // The server provides goto definition support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > definitionProvider;
+
+
+ //
+ // The server provides Goto Type Definition support.
+ //
+ // Since 3.6.0
+ //
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<StaticRegistrationOptions> > > typeDefinitionProvider ;
+
+ // The server provides implementation support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<StaticRegistrationOptions> > > implementationProvider ;
+
+ // The server provides find references support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > referencesProvider ;
+
+ // The server provides document highlight support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentHighlightProvider ;
+
+ // The server provides document symbol support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentSymbolProvider ;
+
+ // The server provides workspace symbol support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > workspaceSymbolProvider ;
+
+ // The server provides code actions.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<CodeActionOptions> > > codeActionProvider ;
+
+ // The server provides code lens.
+ boost::optional<CodeLensOptions> codeLensProvider;
+
+ // The server provides document formatting.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentFormattingProvider ;
+
+ // The server provides document range formatting.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentRangeFormattingProvider ;
+
+ // The server provides document formatting on typing.
+ boost::optional<lsDocumentOnTypeFormattingOptions> documentOnTypeFormattingProvider;
+
+ // The server provides rename support.
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<RenameOptions> > > renameProvider;
+
+
+ // The server provides document link support.
+ boost::optional<lsDocumentLinkOptions > documentLinkProvider;
+
+
+ //
+ // The server provides color provider support.
+ //
+ // @since 3.6.0
+ //
+ boost::optional< std::pair< boost::optional<bool>, boost::optional<DocumentColorOptions> > > colorProvider;
+
+
+ //
+ // The server provides folding provider support.
+ //
+ // @since 3.10.0
+ //
+ boost::optional < std::pair< boost::optional<bool>, boost::optional<FoldingRangeOptions> > > foldingRangeProvider;
+
+ // The server provides execute command support.
+ boost::optional < lsExecuteCommandOptions >executeCommandProvider;
+
+
+ //
+ // Workspace specific server capabilities
+ //
+ boost::optional< WorkspaceServerCapabilities > workspace;
+
+ //
+ // Semantic highlighting server capabilities.
+ //
+
+ boost::optional< SemanticHighlightingServerCapabilities >semanticHighlighting;
+
+ //
+ // Server capability for calculating super- and subtype hierarchies.
+ // The LS supports the type hierarchy language feature, if this capability is set to {@code true}.
+ //
+ // <p>
+ // <b>Note:</b> the <a href=
+ // "https://github.com/Microsoft/vscode-languageserver-node/pull/426">{@code textDocument/typeHierarchy}
+ // language feature</a> is not yet part of the official LSP specification.
+ //
+
+ boost::optional< std::pair< boost::optional<bool>,
+ boost::optional<StaticRegistrationOptions> > > typeHierarchyProvider;
+
+ //
+ // The server provides Call Hierarchy support.
+ //
+
+ boost::optional< std::pair< boost::optional<bool>,
+ boost::optional<StaticRegistrationOptions> > > callHierarchyProvider;
+
+ //
+ // The server provides selection range support.
+ //
+ // Since 3.15.0
+ //
+ boost::optional< std::pair< boost::optional<bool>,
+ boost::optional<StaticRegistrationOptions> > > selectionRangeProvider;
+
+ //
+ // The server provides linked editing range support.
+ //
+ // Since 3.16.0
+ //
+ boost::optional< std::pair< boost::optional<bool>,
+ boost::optional<StaticRegistrationOptions> > > linkedEditingRangeProvider;
+
+
+ //
+ // The server provides semantic tokens support.
+ //
+ // Since 3.16.0
+ //
+ boost::optional < SemanticTokensWithRegistrationOptions> semanticTokensProvider;
+
+ //
+ // Whether server provides moniker support.
+ //
+ // Since 3.16.0
+ //
+ boost::optional< std::pair< boost::optional<bool>,
+ boost::optional<StaticRegistrationOptions> > > monikerProvider;
+
+ boost::optional<lsp::Any> experimental;
+
+
+ MAKE_SWAP_METHOD(lsServerCapabilities,
+ textDocumentSync,
+ hoverProvider,
+ completionProvider,
+ signatureHelpProvider,
+ definitionProvider,
+ typeDefinitionProvider,
+ implementationProvider,
+ referencesProvider,
+ documentHighlightProvider,
+ documentSymbolProvider,
+ workspaceSymbolProvider,
+ codeActionProvider,
+ codeLensProvider,
+ documentFormattingProvider,
+ documentRangeFormattingProvider,
+ documentOnTypeFormattingProvider,
+ renameProvider,
+ documentLinkProvider,
+ executeCommandProvider,
+ workspace,
+ semanticHighlighting,
+ typeHierarchyProvider,
+ callHierarchyProvider,
+ selectionRangeProvider,
+ experimental, colorProvider, foldingRangeProvider,
+ linkedEditingRangeProvider, monikerProvider, semanticTokensProvider)
+
+};
+MAKE_REFLECT_STRUCT(lsServerCapabilities,
+ textDocumentSync,
+ hoverProvider,
+ completionProvider,
+ signatureHelpProvider,
+ definitionProvider,
+ typeDefinitionProvider,
+ implementationProvider,
+ referencesProvider,
+ documentHighlightProvider,
+ documentSymbolProvider,
+ workspaceSymbolProvider,
+ codeActionProvider,
+ codeLensProvider,
+ documentFormattingProvider,
+ documentRangeFormattingProvider,
+ documentOnTypeFormattingProvider,
+ renameProvider,
+ documentLinkProvider,
+ executeCommandProvider,
+ workspace,
+ semanticHighlighting,
+ typeHierarchyProvider,
+ callHierarchyProvider,
+ selectionRangeProvider,
+ experimental, colorProvider, foldingRangeProvider,
+ linkedEditingRangeProvider, monikerProvider, semanticTokensProvider)
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h
new file mode 100644
index 0000000000..569f203c7a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h
@@ -0,0 +1,713 @@
+#pragma once
+#include "LibLsp/lsp/method_type.h"
+
+
+#include <stdexcept>
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/lsp/extention/jdtls/searchSymbols.h"
+#include "lsWorkspaceClientCapabilites.h"
+#include "LibLsp/lsp/lsp_completion.h"
+#include "LibLsp/lsp/lsp_diagnostic.h"
+
+
+struct WorkDoneProgressOptions
+{
+ boost::optional<bool>workDoneProgress;
+ MAKE_SWAP_METHOD(WorkDoneProgressOptions, workDoneProgress);
+};
+MAKE_REFLECT_STRUCT(WorkDoneProgressOptions, workDoneProgress);
+
+// Completion options.
+struct lsCompletionOptions:WorkDoneProgressOptions
+{
+ // The server provides support to resolve additional
+ // information for a completion item.
+ boost::optional<bool> resolveProvider = false;
+
+ //
+ // Most tools trigger completion request automatically without explicitly requesting
+ // it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user
+ // starts to type an identifier. For example if the user types `c` in a JavaScript file
+ // code complete will automatically pop up present `console` besides others as a
+ // completion item. Characters that make up identifiers don't need to be listed here.
+ //
+ // If code complete should automatically be trigger on characters not being valid inside
+ // an identifier (for example `.` in JavaScript) list them in `triggerCharacters`.
+ //
+ // https://github.com/Microsoft/language-server-protocol/issues/138.
+ boost::optional< std::vector<std::string> > triggerCharacters ;
+
+ //
+ // The list of all possible characters that commit a completion. This field can be used
+ // if clients don't support individual commmit characters per completion item. See
+ // `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
+ //
+ boost::optional< std::vector<std::string> > allCommitCharacters;
+
+ MAKE_SWAP_METHOD(lsCompletionOptions, workDoneProgress, resolveProvider, triggerCharacters, allCommitCharacters);
+};
+MAKE_REFLECT_STRUCT(lsCompletionOptions, workDoneProgress, resolveProvider, triggerCharacters,allCommitCharacters);
+
+
+
+// Save options.
+struct lsSaveOptions {
+ // The client is supposed to include the content on save.
+ bool includeText = false;
+ void swap(lsSaveOptions& arg)noexcept
+ {
+ auto temp = includeText;
+ includeText = arg.includeText;
+ arg.includeText = temp;
+ }
+};
+MAKE_REFLECT_STRUCT(lsSaveOptions, includeText);
+
+// Signature help options.
+struct lsSignatureHelpOptions : WorkDoneProgressOptions {
+ // The characters that trigger signature help automatically.
+ // NOTE: If updating signature help tokens make sure to also update
+ // WorkingFile::FindClosestCallNameInBuffer.
+ std::vector<std::string> triggerCharacters;
+ MAKE_SWAP_METHOD(lsSignatureHelpOptions, workDoneProgress, triggerCharacters);
+};
+MAKE_REFLECT_STRUCT(lsSignatureHelpOptions, workDoneProgress, triggerCharacters);
+
+// Defines how the host (editor) should sync document changes to the language
+// server.
+enum class lsTextDocumentSyncKind {
+ // Documents should not be synced at all.
+ None = 0,
+
+ // Documents are synced by always sending the full content
+ // of the document.
+ Full = 1,
+
+ // Documents are synced by sending the full content on open.
+ // After that only incremental updates to the document are
+ // send.
+ Incremental = 2
+};
+
+#if _WIN32
+MAKE_REFLECT_TYPE_PROXY(lsTextDocumentSyncKind)
+#else
+//#pragma clang diagnostic push
+//#pragma clang diagnostic ignored "-Wunused-function"
+MAKE_REFLECT_TYPE_PROXY(lsTextDocumentSyncKind)
+//#pragma clang diagnostic pop
+#endif
+
+struct lsTextDocumentSyncOptions {
+ // Open and close notifications are sent to the server.
+ boost::optional<bool> openClose ;
+ // Change notificatins are sent to the server. See TextDocumentSyncKind.None,
+ // TextDocumentSyncKind.Full and TextDocumentSyncKindIncremental.
+ boost::optional< lsTextDocumentSyncKind> change ;
+ // Will save notifications are sent to the server.
+ boost::optional<bool> willSave;
+ // Will save wait until requests are sent to the server.
+ boost::optional<bool> willSaveWaitUntil;
+ // Save notifications are sent to the server.
+ boost::optional<lsSaveOptions> save;
+
+ MAKE_SWAP_METHOD(lsTextDocumentSyncOptions,
+ openClose,
+ change,
+ willSave,
+ willSaveWaitUntil,
+ save);
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions,
+ openClose,
+ change,
+ willSave,
+ willSaveWaitUntil,
+ save);
+
+struct SynchronizationCapabilities {
+ // Whether text document synchronization supports dynamic registration.
+ boost::optional<bool> dynamicRegistration;
+
+ // The client supports sending will save notifications.
+ boost::optional<bool> willSave;
+
+ // The client supports sending a will save request and
+ // waits for a response providing text edits which will
+ // be applied to the document before it is saved.
+ boost::optional<bool> willSaveWaitUntil;
+
+ // The client supports did save notifications.
+ boost::optional<bool> didSave;
+
+ MAKE_SWAP_METHOD(SynchronizationCapabilities,
+ dynamicRegistration,
+ willSave,
+ willSaveWaitUntil,
+ didSave);
+};
+MAKE_REFLECT_STRUCT(SynchronizationCapabilities,
+ dynamicRegistration,
+ willSave,
+ willSaveWaitUntil,
+ didSave);
+
+struct CompletionItemKindCapabilities
+{
+ boost::optional<std::vector<lsCompletionItemKind> >valueSet;
+ MAKE_SWAP_METHOD(CompletionItemKindCapabilities, valueSet);
+};
+MAKE_REFLECT_STRUCT(CompletionItemKindCapabilities, valueSet);
+
+struct CompletionItemCapabilities {
+ // Client supports snippets as insert text.
+ //
+ // A snippet can define tab stops and placeholders with `$1`, `$2`
+ // and `${3:foo}`. `$0` defines the final tab stop, it defaults to
+ // the end of the snippet. Placeholders with equal identifiers are linked,
+ // that is typing in one will update others too.
+ boost::optional<bool> snippetSupport;
+
+ // Client supports commit characters on a completion item.
+
+ boost::optional<bool> commitCharactersSupport;
+
+
+ // Client supports the following content formats for the documentation
+ // property. The order describes the preferred format of the client.
+
+ boost::optional< std::vector<std::string> > documentationFormat;
+
+ // Client supports the deprecated property on a completion item.
+
+ boost::optional<bool> deprecatedSupport;
+
+ //
+ // Client supports the preselect property on a completion item.
+ //
+ boost::optional<bool> preselectSupport;
+
+ MAKE_SWAP_METHOD(CompletionItemCapabilities,
+ snippetSupport,
+ commitCharactersSupport,
+ documentationFormat,
+ deprecatedSupport, preselectSupport);
+};
+MAKE_REFLECT_STRUCT(CompletionItemCapabilities,
+ snippetSupport,
+ commitCharactersSupport,
+ documentationFormat,
+ deprecatedSupport, preselectSupport);
+
+
+//
+ // Capabilities specific to the `textDocument/completion`
+ //
+struct CompletionCapabilities {
+ // Whether completion supports dynamic registration.
+ boost::optional<bool> dynamicRegistration;
+
+
+
+ // The client supports the following `CompletionItem` specific
+ // capabilities.
+ boost::optional<CompletionItemCapabilities> completionItem;
+
+ //
+ // The client supports the following `CompletionItemKind` specific
+ // capabilities.
+ //
+ boost::optional<CompletionItemKindCapabilities> completionItemKind;
+
+ //
+ // The client supports sending additional context information for a
+ // `textDocument/completion` request.
+ //
+ boost::optional<bool> contextSupport;
+
+
+ MAKE_SWAP_METHOD(CompletionCapabilities,
+ dynamicRegistration,
+ completionItem, completionItemKind);
+};
+
+MAKE_REFLECT_STRUCT(CompletionCapabilities,
+ dynamicRegistration,
+ completionItem , completionItemKind);
+
+
+struct HoverCapabilities:public DynamicRegistrationCapabilities
+{
+ //
+ // Client supports the following content formats for the content
+ // property. The order describes the preferred format of the client.
+ //
+ // See {@link MarkupKind} for allowed values.
+ //
+ boost::optional<std::vector<std::string>> contentFormat;
+
+ MAKE_SWAP_METHOD(HoverCapabilities, dynamicRegistration, contentFormat);
+};
+MAKE_REFLECT_STRUCT(HoverCapabilities, dynamicRegistration, contentFormat);
+
+//
+ // Client capabilities specific to parameter information.
+ //
+struct ParameterInformationCapabilities {
+ //
+ // The client supports processing label offsets instead of a
+ // simple label string.
+ //
+ // Since 3.14.0
+ //
+ boost::optional<bool> labelOffsetSupport;
+
+ MAKE_SWAP_METHOD(ParameterInformationCapabilities, labelOffsetSupport);
+};
+MAKE_REFLECT_STRUCT(ParameterInformationCapabilities, labelOffsetSupport)
+
+
+struct SignatureInformationCapabilities {
+ //
+ // Client supports the following content formats for the documentation
+ // property. The order describes the preferred format of the client.
+ //
+ // See {@link MarkupKind} for allowed values.
+ //
+ std::vector<std::string> documentationFormat;
+
+ //
+ // Client capabilities specific to parameter information.
+ //
+ ParameterInformationCapabilities parameterInformation;
+
+ MAKE_SWAP_METHOD(SignatureInformationCapabilities, documentationFormat, parameterInformation)
+};
+MAKE_REFLECT_STRUCT(SignatureInformationCapabilities,documentationFormat, parameterInformation)
+
+struct SignatureHelpCapabilities :public DynamicRegistrationCapabilities
+{
+ //
+ // The client supports the following `SignatureInformation`
+ // specific properties.
+ //
+ boost::optional< SignatureInformationCapabilities > signatureInformation;
+
+ MAKE_SWAP_METHOD(SignatureHelpCapabilities, dynamicRegistration, signatureInformation)
+};
+MAKE_REFLECT_STRUCT(SignatureHelpCapabilities, dynamicRegistration, signatureInformation)
+
+struct DocumentSymbolCapabilities :public DynamicRegistrationCapabilities {
+ //
+ // Specific capabilities for the `SymbolKind`.
+ //
+ boost::optional<SymbolKindCapabilities> symbolKind;
+
+ //
+ // The client support hierarchical document symbols.
+ //
+ boost::optional<bool> hierarchicalDocumentSymbolSupport;
+
+ MAKE_SWAP_METHOD(DocumentSymbolCapabilities, dynamicRegistration, symbolKind, hierarchicalDocumentSymbolSupport)
+};
+MAKE_REFLECT_STRUCT(DocumentSymbolCapabilities, dynamicRegistration, symbolKind, hierarchicalDocumentSymbolSupport)
+
+struct DeclarationCapabilities:public DynamicRegistrationCapabilities{
+ //
+ // The client supports additional metadata in the form of declaration links.
+ //
+ boost::optional<bool>linkSupport;
+
+ MAKE_SWAP_METHOD(DeclarationCapabilities, dynamicRegistration, linkSupport);
+};
+MAKE_REFLECT_STRUCT(DeclarationCapabilities, dynamicRegistration, linkSupport)
+
+
+struct CodeActionKindCapabilities
+{
+ //
+ // The code action kind values the client supports. When this
+ // property exists the client also guarantees that it will
+ // handle values outside its set gracefully and falls back
+ // to a default value when unknown.
+ //
+ // See {@link CodeActionKind} for allowed values.
+ //
+ boost::optional< std::vector< std::string> >valueSet;
+
+ MAKE_SWAP_METHOD(CodeActionKindCapabilities, valueSet)
+};
+MAKE_REFLECT_STRUCT(CodeActionKindCapabilities,valueSet)
+
+struct CodeActionLiteralSupportCapabilities
+{
+ boost::optional<CodeActionKindCapabilities> codeActionKind;
+
+ MAKE_SWAP_METHOD(CodeActionLiteralSupportCapabilities, codeActionKind)
+};
+MAKE_REFLECT_STRUCT(CodeActionLiteralSupportCapabilities, codeActionKind)
+
+struct CodeActionCapabilities:public DynamicRegistrationCapabilities{
+ //
+ // The client support code action literals as a valid
+ // response of the `textDocument/codeAction` request.
+ //
+ boost::optional<CodeActionLiteralSupportCapabilities> codeActionLiteralSupport;
+
+ MAKE_SWAP_METHOD(CodeActionCapabilities, dynamicRegistration, codeActionLiteralSupport)
+};
+MAKE_REFLECT_STRUCT(CodeActionCapabilities,dynamicRegistration,codeActionLiteralSupport)
+
+struct RenameCapabilities :public DynamicRegistrationCapabilities {
+ //
+ // The client support code action literals as a valid
+ // response of the `textDocument/codeAction` request.
+ //
+ boost::optional<bool> prepareSupport;
+
+ MAKE_SWAP_METHOD(RenameCapabilities, dynamicRegistration, prepareSupport)
+};
+MAKE_REFLECT_STRUCT(RenameCapabilities, dynamicRegistration, prepareSupport)
+
+struct DiagnosticsTagSupport {
+ /**
+ * The tags supported by the client.
+ */
+ std::vector<DiagnosticTag> valueSet;
+ MAKE_SWAP_METHOD(DiagnosticsTagSupport, valueSet)
+};
+MAKE_REFLECT_STRUCT(DiagnosticsTagSupport, valueSet)
+
+struct PublishDiagnosticsClientCapabilities :public DynamicRegistrationCapabilities {
+ /**
+ * The client support code action literals as a valid
+ * response of the `textDocument/codeAction` request.
+ */
+ boost::optional<bool> relatedInformation;
+
+ /**
+ * Client supports the tag property to provide meta data about a diagnostic.
+ * Clients supporting tags have to handle unknown tags gracefully.
+ *
+ * This property had been added and implemented as boolean before it was
+ * added to the specification as {@link DiagnosticsTagSupport}. In order to
+ * keep this implementation compatible with intermediate clients (including
+ * vscode-language-client < 6.0.0) we add an either type here.
+ *
+ * Since 3.15
+ */
+ boost::optional < std::pair<boost::optional<bool>, boost::optional<DiagnosticsTagSupport> > > tagSupport;
+
+ /**
+ * Whether the client interprets the version property of the
+ * `textDocument/publishDiagnostics` notification's parameter.
+ *
+ * Since 3.15.0
+ */
+ boost::optional<bool> versionSupport;
+
+ /**
+ * Client supports a codeDescription property
+ *
+ * @since 3.16.0
+ */
+ boost::optional<bool> codeDescriptionSupport ;
+
+ /**
+ * Whether code action supports the `data` property which is
+ * preserved between a `textDocument/publishDiagnostics` and
+ * `textDocument/codeAction` request.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<bool> dataSupport ;
+
+
+ MAKE_SWAP_METHOD(PublishDiagnosticsClientCapabilities, dynamicRegistration, relatedInformation, tagSupport,versionSupport,codeDescriptionSupport,dataSupport)
+};
+MAKE_REFLECT_STRUCT(PublishDiagnosticsClientCapabilities, dynamicRegistration, relatedInformation, tagSupport, versionSupport, codeDescriptionSupport, dataSupport)
+
+
+struct FoldingRangeCapabilities :public DynamicRegistrationCapabilities {
+ //
+ // The maximum number of folding ranges that the client prefers to receive per document. The value serves as a
+ // hint, servers are free to follow the limit.
+ //
+ boost::optional<int> rangeLimit;
+
+ //
+ // If set, the client signals that it only supports folding complete lines. If set, client will
+ // ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange.
+ //
+ boost::optional<bool> lineFoldingOnly;
+ MAKE_SWAP_METHOD(FoldingRangeCapabilities, dynamicRegistration, rangeLimit, lineFoldingOnly)
+};
+MAKE_REFLECT_STRUCT(FoldingRangeCapabilities, dynamicRegistration, rangeLimit,lineFoldingOnly)
+
+
+struct SemanticHighlightingCapabilities :public DynamicRegistrationCapabilities {
+ //
+ // The client support code action literals as a valid
+ // response of the `textDocument/codeAction` request.
+ //
+ boost::optional<bool> semanticHighlighting;
+
+ MAKE_SWAP_METHOD(SemanticHighlightingCapabilities, dynamicRegistration, semanticHighlighting)
+};
+MAKE_REFLECT_STRUCT(SemanticHighlightingCapabilities, dynamicRegistration, semanticHighlighting)
+
+struct SemanticTokensClientCapabilitiesRequestsFull {
+
+ //
+ // The client will send the `textDocument/semanticTokens/full/delta` request if
+ // the server provides a corresponding handler.
+ //
+ bool delta = false;
+ MAKE_SWAP_METHOD(SemanticTokensClientCapabilitiesRequestsFull, delta)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensClientCapabilitiesRequestsFull, delta)
+
+struct SemanticTokensClientCapabilities : public DynamicRegistrationCapabilities
+{
+ //export TokenFormat = 'relative';
+ struct lsRequests
+ {
+ //
+ // The client will send the `textDocument/semanticTokens/range` request
+ // if the server provides a corresponding handler.
+ //
+ boost::optional<std::pair< boost::optional<bool>,
+ boost::optional<SemanticTokensClientCapabilitiesRequestsFull>>> range;
+ //
+ // The client will send the `textDocument/semanticTokens/full` request
+ // if the server provides a corresponding handler.
+ //
+ boost::optional<std::pair< boost::optional<bool>, boost::optional<lsp::Any>>> full;
+ MAKE_SWAP_METHOD(lsRequests, range, full)
+ };
+
+ lsRequests requests;
+ //
+ // The token types that the client supports.
+ //
+ std::vector<std::string> tokenTypes;
+
+ //
+ // The token modifiers that the client supports.
+ //
+ std::vector<std::string> tokenModifiers;
+ //
+ // The formats the clients supports.
+ //
+ std::vector<std::string> formats;
+ //
+ // Whether the client supports tokens that can overlap each other.
+ //
+ boost::optional < bool >overlappingTokenSupport;
+
+ //
+ // Whether the client supports tokens that can span multiple lines.
+ //
+ boost::optional < bool > multilineTokenSupport;
+
+ MAKE_SWAP_METHOD(SemanticTokensClientCapabilities, dynamicRegistration,requests, tokenTypes, tokenModifiers,
+ formats, overlappingTokenSupport, multilineTokenSupport)
+
+};
+MAKE_REFLECT_STRUCT(SemanticTokensClientCapabilities::lsRequests, range,full)
+MAKE_REFLECT_STRUCT(SemanticTokensClientCapabilities, dynamicRegistration, requests, tokenTypes, tokenModifiers,
+ formats, overlappingTokenSupport, multilineTokenSupport)
+
+// Text document specific client capabilities.
+struct lsTextDocumentClientCapabilities {
+
+ SynchronizationCapabilities synchronization;
+
+
+ // Capabilities specific to the `textDocument/completion`
+ boost::optional<CompletionCapabilities> completion;
+
+
+
+ // Capabilities specific to the `textDocument/hover`
+ boost::optional<HoverCapabilities> hover;
+
+ // Capabilities specific to the `textDocument/signatureHelp`
+ boost::optional<SignatureHelpCapabilities> signatureHelp;
+
+ // Capabilities specific to the `textDocument/references`
+ boost::optional<DynamicRegistrationCapabilities> references;
+
+
+
+
+
+ // Capabilities specific to the `textDocument/documentHighlight`
+ boost::optional<DynamicRegistrationCapabilities> documentHighlight;
+
+ // Capabilities specific to the `textDocument/documentSymbol`
+ boost::optional<DocumentSymbolCapabilities> documentSymbol;
+
+ // Capabilities specific to the `textDocument/formatting`
+ boost::optional<DynamicRegistrationCapabilities> formatting;
+
+ // Capabilities specific to the `textDocument/rangeFormatting`
+ boost::optional<DynamicRegistrationCapabilities> rangeFormatting;
+
+ // Capabilities specific to the `textDocument/onTypeFormatting`
+ boost::optional<DynamicRegistrationCapabilities> onTypeFormatting;
+
+
+ //
+ // Capabilities specific to the `textDocument/declaration`
+ //
+ // Since 3.14.0
+ //
+ boost::optional< DeclarationCapabilities> declaration;
+
+
+ typedef DeclarationCapabilities DefinitionCapabilities;
+ // Capabilities specific to the `textDocument/definition`
+ boost::optional<DefinitionCapabilities> definition;
+
+
+
+ //
+// Capabilities specific to the `textDocument/typeDefinition`
+//
+// Since 3.6.0
+//
+ typedef DeclarationCapabilities TypeDefinitionCapabilities;
+ boost::optional<TypeDefinitionCapabilities> typeDefinition;
+
+
+ typedef DeclarationCapabilities ImplementationCapabilities;
+ // Capabilities specific to the `textDocument/implementation`
+ boost::optional<ImplementationCapabilities> implementation;
+
+
+ // Capabilities specific to the `textDocument/codeAction`
+ boost::optional<CodeActionCapabilities> codeAction;
+
+
+ // Capabilities specific to the `textDocument/codeLens`
+ boost::optional<DynamicRegistrationCapabilities> codeLens;
+
+ // Capabilities specific to the `textDocument/documentLink`
+ boost::optional<DynamicRegistrationCapabilities> documentLink;
+
+ //
+ // Capabilities specific to the `textDocument/documentColor` and the
+ // `textDocument/colorPresentation` request.
+ //
+ // Since 3.6.0
+ //
+ boost::optional<DynamicRegistrationCapabilities> colorProvider;
+
+ // Capabilities specific to the `textDocument/rename`
+ boost::optional<RenameCapabilities> rename;
+
+//
+// Capabilities specific to `textDocument/publishDiagnostics`.
+//
+ boost::optional<PublishDiagnosticsClientCapabilities> publishDiagnostics;
+
+ //
+// Capabilities specific to `textDocument/foldingRange` requests.
+//
+// Since 3.10.0
+//
+ boost::optional< FoldingRangeCapabilities > foldingRange;
+
+
+ //
+ // Capabilities specific to {@code textDocument/semanticHighlighting}.
+ //
+ boost::optional< SemanticHighlightingCapabilities > semanticHighlightingCapabilities;
+
+ //
+ // Capabilities specific to {@code textDocument/typeHierarchy}.
+ //
+ boost::optional< DynamicRegistrationCapabilities > typeHierarchyCapabilities;
+
+
+
+ //
+// Capabilities specific to `textDocument/selectionRange` requests
+//
+
+ boost::optional< DynamicRegistrationCapabilities > selectionRange;
+
+ //
+ // Capabilities specific to the `textDocument/linkedEditingRange` request.
+ //
+ // @since 3.16.0
+ //
+ boost::optional< DynamicRegistrationCapabilities > linkedEditingRange;
+
+ //
+ // Capabilities specific to the various call hierarchy requests.
+ //
+ // @since 3.16.0
+ //
+ boost::optional< DynamicRegistrationCapabilities > callHierarchy;
+
+ //
+ // Capabilities specific to the various semantic token requests.
+ //
+ // @since 3.16.0
+ //
+ boost::optional< SemanticTokensClientCapabilities > semanticTokens;
+
+ //
+ // Capabilities specific to the `textDocument/moniker` request.
+ //
+ // @since 3.16.0
+ //
+ boost::optional< DynamicRegistrationCapabilities > moniker;
+
+ MAKE_SWAP_METHOD(lsTextDocumentClientCapabilities,
+ synchronization,
+ completion,
+ hover,
+ signatureHelp,
+ implementation,
+ references,
+ documentHighlight,
+ documentSymbol,
+ formatting,
+ rangeFormatting,
+ onTypeFormatting,
+ declaration,
+ definition, typeDefinition, implementation,
+ codeAction,
+ codeLens,
+ documentLink, colorProvider,
+ rename, publishDiagnostics, foldingRange,
+ semanticHighlightingCapabilities, typeHierarchyCapabilities,
+ callHierarchy, selectionRange , linkedEditingRange, semanticTokens, moniker)
+};
+
+
+MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities,
+ synchronization,
+ completion,
+ hover,
+ signatureHelp,
+ implementation,
+ references,
+ documentHighlight,
+ documentSymbol,
+ formatting,
+ rangeFormatting,
+ onTypeFormatting,
+ declaration,
+ definition, typeDefinition, implementation,
+ codeAction,
+ codeLens,
+ documentLink, colorProvider,
+ rename, publishDiagnostics, foldingRange,
+ semanticHighlightingCapabilities, typeHierarchyCapabilities,
+ callHierarchy, selectionRange, linkedEditingRange, semanticTokens, moniker)
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h
new file mode 100644
index 0000000000..dd37a1af2f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h
@@ -0,0 +1,256 @@
+#pragma once
+#include "LibLsp/lsp/method_type.h"
+
+
+#include <stdexcept>
+
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/lsp/extention/jdtls/searchSymbols.h"
+
+/**
+ * Capabilities specific to `WorkspaceEdit`s
+ */
+
+//New in version 3.13: ResourceOperationKind and FailureHandlingKind and the client capability workspace.workspaceEdit.
+//resourceOperations as well as workspace.workspaceEdit.failureHandling.
+
+//The capabilities of a workspace edit has evolved over the time.
+//Clients can describe their support using the following client capability :
+
+struct lschangeAnnotationSupport
+{
+ /**
+ * Whether the client groups edits with equal labels into tree nodes,
+ * for instance all edits labelled with "Changes in Strings" would
+ * be a tree node.
+ */
+ boost::optional<bool> groupsOnLabel;
+ MAKE_SWAP_METHOD(lschangeAnnotationSupport, groupsOnLabel)
+};
+MAKE_REFLECT_STRUCT(lschangeAnnotationSupport, groupsOnLabel)
+
+struct WorkspaceEditCapabilities {
+ /**
+ * The client supports versioned document changes in `WorkspaceEdit`s
+ */
+ boost::optional<bool> documentChanges;
+
+ /**
+ * The client supports resource changes
+ * in `WorkspaceEdit`s.
+ *
+ * @deprecated Since LSP introduces resource operations, use {link #resourceOperations}
+ */
+
+ boost::optional<bool> resourceChanges;
+
+ /**
+ * The resource operations the client supports. Clients should at least
+ * support 'create', 'rename' and 'delete' files and folders.
+ *
+ * @since 3.13.0
+ */
+ boost::optional< std::vector<std::string> > resourceOperations;
+
+ /**
+ * The failure handling strategy of a client if applying the workspace edit
+ * fails.
+ *
+ * See {@link FailureHandlingKind} for allowed values.
+ */
+ boost::optional<std::string > failureHandling;
+
+ /**
+ * Whether the client normalizes line endings to the client specific
+ * setting.
+ * If set to `true` the client will normalize line ending characters
+ * in a workspace edit to the client specific new line character(s).
+ *
+ * @since 3.16.0
+ */
+ boost::optional<bool> normalizesLineEndings;;
+
+ /**
+ * Whether the client in general supports change annotations on text edits,
+ * create file, rename file and delete file changes.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<lschangeAnnotationSupport> changeAnnotationSupport;
+
+ MAKE_SWAP_METHOD(WorkspaceEditCapabilities, documentChanges, resourceChanges, resourceOperations, failureHandling, normalizesLineEndings, changeAnnotationSupport)
+
+};
+MAKE_REFLECT_STRUCT(WorkspaceEditCapabilities,documentChanges, resourceChanges, resourceOperations, failureHandling, normalizesLineEndings, changeAnnotationSupport)
+
+
+struct DynamicRegistrationCapabilities {
+ // Did foo notification supports dynamic registration.
+ boost::optional<bool> dynamicRegistration;
+
+ MAKE_SWAP_METHOD(DynamicRegistrationCapabilities,
+ dynamicRegistration);
+};
+
+MAKE_REFLECT_STRUCT(DynamicRegistrationCapabilities,
+ dynamicRegistration);
+
+
+
+// Workspace specific client capabilities.
+struct SymbolKindCapabilities
+{
+ boost::optional< std::vector<lsSymbolKind> > valueSet;
+
+ MAKE_SWAP_METHOD(SymbolKindCapabilities, valueSet)
+
+
+};
+MAKE_REFLECT_STRUCT(SymbolKindCapabilities, valueSet)
+
+
+
+
+struct SymbolCapabilities :public DynamicRegistrationCapabilities {
+ /**
+ * Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
+ */
+ boost::optional<SymbolKindCapabilities> symbolKind;
+
+ MAKE_SWAP_METHOD(SymbolCapabilities,
+ symbolKind, dynamicRegistration)
+};
+MAKE_REFLECT_STRUCT(SymbolCapabilities,
+ symbolKind, dynamicRegistration)
+
+
+struct lsFileOperations
+{
+ /**
+ * Whether the client supports dynamic registration for file
+ * requests/notifications.
+ */
+ boost::optional<bool> dynamicRegistration ;
+
+ /**
+ * The client has support for sending didCreateFiles notifications.
+ */
+ boost::optional<bool>didCreate ;
+
+ /**
+ * The client has support for sending willCreateFiles requests.
+ */
+ boost::optional<bool>willCreate ;
+
+ /**
+ * The client has support for sending didRenameFiles notifications.
+ */
+ boost::optional<bool>didRename ;
+
+ /**
+ * The client has support for sending willRenameFiles requests.
+ */
+ boost::optional<bool>willRename ;
+
+ /**
+ * The client has support for sending didDeleteFiles notifications.
+ */
+ boost::optional<bool>didDelete ;
+
+ /**
+ * The client has support for sending willDeleteFiles requests.
+ */
+ boost::optional<bool> willDelete ;
+ MAKE_SWAP_METHOD(lsFileOperations, dynamicRegistration, didCreate, willCreate,
+ didRename, willRename, didDelete, willDelete)
+};
+MAKE_REFLECT_STRUCT(lsFileOperations, dynamicRegistration, didCreate, willCreate,
+ didRename, willRename, didDelete, willDelete)
+
+struct lsWorkspaceClientCapabilites {
+ // The client supports applying batch edits to the workspace.
+ boost::optional<bool> applyEdit;
+
+
+
+ // Capabilities specific to `WorkspaceEdit`s
+ boost::optional<WorkspaceEditCapabilities> workspaceEdit;
+
+
+
+ // Capabilities specific to the `workspace/didChangeConfiguration`
+ // notification.
+ boost::optional<DynamicRegistrationCapabilities> didChangeConfiguration;
+
+ // Capabilities specific to the `workspace/didChangeWatchedFiles`
+ // notification.
+ boost::optional<DynamicRegistrationCapabilities> didChangeWatchedFiles;
+
+ // Capabilities specific to the `workspace/symbol` request.
+ boost::optional<SymbolCapabilities> symbol;
+
+ // Capabilities specific to the `workspace/executeCommand` request.
+ boost::optional<DynamicRegistrationCapabilities> executeCommand;
+
+
+ /**
+ * The client has support for workspace folders.
+ *
+ * Since 3.6.0
+ */
+ boost::optional<bool> workspaceFolders;
+
+ /**
+ * The client supports `workspace/configuration` requests.
+ *
+ * Since 3.6.0
+ */
+ boost::optional<bool> configuration;
+
+
+ /**
+ * Capabilities specific to the semantic token requests scoped to the
+ * workspace.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<DynamicRegistrationCapabilities> semanticTokens ;
+
+ /**
+ * Capabilities specific to the code lens requests scoped to the
+ * workspace.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<DynamicRegistrationCapabilities> codeLens ;
+
+ /**
+ * The client has support for file requests/notifications.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<lsFileOperations> fileOperations;
+
+ MAKE_SWAP_METHOD(lsWorkspaceClientCapabilites,
+ applyEdit,
+ workspaceEdit,
+ didChangeConfiguration,
+ didChangeWatchedFiles,
+ symbol,executeCommand, workspaceFolders,
+ configuration, semanticTokens, codeLens, fileOperations)
+};
+
+MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites,
+ applyEdit,
+ workspaceEdit,
+ didChangeConfiguration,
+ didChangeWatchedFiles,
+ symbol,
+ executeCommand,workspaceFolders,
+ configuration, semanticTokens, codeLens, fileOperations)
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/progress.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/progress.h
new file mode 100644
index 0000000000..01cb18d68d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/progress.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/lsp/lsAny.h"
+//The base protocol offers also support to report progress in a generic fashion.
+//This mechanism can be used to report any kind of progress including work done
+//progress(usually used to report progress in the user interface using a progress bar)
+//and partial result progress to support streaming of results.
+struct ProgressParams
+{
+ std::pair<boost::optional<std::string> , boost::optional<int> > token;
+ lsp::Any value;
+ MAKE_SWAP_METHOD(ProgressParams, token, value)
+};
+MAKE_REFLECT_STRUCT(ProgressParams, token, value)
+DEFINE_NOTIFICATION_TYPE(Notify_Progress, ProgressParams, "$/progress");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/general/shutdown.h b/graphics/asymptote/LspCpp/LibLsp/lsp/general/shutdown.h
new file mode 100644
index 0000000000..5366ff89d6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/general/shutdown.h
@@ -0,0 +1,15 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+
+/**
+ * The shutdown request is sent from the client to the server. It asks the
+ * server to shutdown, but to not exit (otherwise the response might not be
+ * delivered correctly to the client). There is a separate exit notification
+ * that asks the server to exit.
+ */
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_shutdown, boost::optional<JsonNull>, boost::optional<lsp::Any>, "shutdown");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/language/language.h b/graphics/asymptote/LspCpp/LibLsp/lsp/language/language.h
new file mode 100644
index 0000000000..b4c7829e95
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/language/language.h
@@ -0,0 +1,170 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsCommand.h"
+
+#ifdef _WIN32
+#include <ppltasks.h>
+#endif
+
+struct StatusReport {
+
+ std::string ToString() const
+ {
+ std::string info;
+ info += "type:" + type + "\n";
+ info += "message:" + message + "\n";
+ return info;
+ }
+ /**
+ * The message type. See {
+ *
+ */
+
+ std::string type;
+ /**
+ * The actual message
+ *
+ */
+
+ std::string message;
+ MAKE_SWAP_METHOD(StatusReport, type, message);
+};
+MAKE_REFLECT_STRUCT(StatusReport, type, message);
+
+/**
+ * The show message notification is sent from a server to a client to ask
+ * the client to display a particular message in the user interface.
+ */
+DEFINE_NOTIFICATION_TYPE(lang_status, StatusReport, "language/status");
+
+
+enum class MessageType {
+
+ /**
+ * An error message.
+ */
+ Error=(1),
+
+ /**
+ * A warning message.
+ */
+ Warning=(2),
+
+ /**
+ * An information message.
+ */
+ Info=(3),
+
+ /**
+ * A log message.
+ */
+ Log=(4)
+};
+MAKE_REFLECT_TYPE_PROXY(MessageType);
+
+
+struct ActionableNotification {
+
+
+
+ /**
+ * The message type. See {
+ *
+ */
+
+ MessageType severity;
+ /**
+ * The actual message
+ *
+ */
+
+ std::string message;
+
+ /**
+ * Optional data
+ *
+ */
+
+ boost::optional<lsp::Any> data;
+
+
+ /**
+ * Optional commands
+ *
+ */
+
+ std::vector<lsCommandWithAny> commands;
+
+ MAKE_SWAP_METHOD(ActionableNotification, severity, message, data, commands)
+};
+MAKE_REFLECT_STRUCT(ActionableNotification, severity, message, data, commands)
+
+
+/**
+ * The actionable notification is sent from a server to a client to ask the
+ * client to display a particular message in the user interface, and possible
+ * commands to execute. The commands must be implemented on the client side.
+ */
+DEFINE_NOTIFICATION_TYPE(lang_actionableNotification, ActionableNotification, "language/actionableNotification");
+
+
+
+struct ProgressReport {
+ std::string ToString() const;
+
+ std::string id;
+
+
+ std::string task;
+
+
+ std::string subTask;
+
+
+ std::string status;
+
+ int totalWork = 0;
+
+
+ int workDone = 0;
+
+
+ bool complete = false;
+ MAKE_SWAP_METHOD(ProgressReport, id, task, subTask, status, workDone, complete);
+};
+
+
+MAKE_REFLECT_STRUCT(ProgressReport, id, task, subTask, status, workDone, complete);
+
+/**
+ * The progress report notification is sent from a server to be handled by the
+ * client.
+ */
+DEFINE_NOTIFICATION_TYPE(lang_progressReport, ProgressReport, "language/progressReport");
+
+enum EventType {
+ /**
+ * classpath updated event.
+ */
+ ClasspathUpdated = (100),
+
+ /**
+ * projects imported event.
+ */
+ ProjectsImported = (200)
+};
+
+struct EventNotification
+{
+ int eventType;
+ lsp::Any data;
+ std::string ToString() const;
+ MAKE_SWAP_METHOD(EventNotification, eventType, data)
+};
+MAKE_REFLECT_STRUCT(EventNotification, eventType, data);
+
+DEFINE_NOTIFICATION_TYPE(lang_eventNotification, EventNotification, "language/eventNotification"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/location_type.h b/graphics/asymptote/LspCpp/LibLsp/lsp/location_type.h
new file mode 100644
index 0000000000..14e130f571
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/location_type.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include "lsDocumentUri.h"
+#include "lsRange.h"
+//Represents a location inside a resource, such as a line inside a text file.
+struct lsLocation {
+ lsLocation();
+ lsLocation(lsDocumentUri uri, lsRange range);
+
+ bool operator==(const lsLocation& other) const;
+ bool operator<(const lsLocation& o) const;
+
+ lsDocumentUri uri;
+ lsRange range;
+ MAKE_SWAP_METHOD(lsLocation, uri, range)
+};
+MAKE_REFLECT_STRUCT(lsLocation, uri, range)
+
+
+
+struct LinkLocation :public lsLocation
+{
+ std::string displayName;
+ std::string kind;
+ MAKE_REFLECT_STRUCT(LinkLocation, uri, range, displayName, kind)
+};
+MAKE_REFLECT_STRUCT(LinkLocation, uri, range, displayName,kind)
+
+//Represents a link between a sourceand a target location.
+struct LocationLink
+{
+ /**
+ * Span of the origin of this link.
+ *
+ * Used as the underlined span for mouse interaction. Defaults to the word range at
+ * the mouse position.
+ */
+ boost::optional<lsRange> originSelectionRange;
+
+ /**
+ * The target resource identifier of this link.
+ */
+
+ lsDocumentUri targetUri;
+
+ /**
+ * The full target range of this link. If the target for example is a symbol then target range is the
+ * range enclosing this symbol not including leading/trailing whitespace but everything else
+ * like comments. This information is typically used to highlight the range in the editor.
+ */
+
+ lsRange targetRange;
+
+ /**
+ * The range that should be selected and revealed when this link is being followed, e.g the name of a function.
+ * Must be contained by the the `targetRange`. See also `DocumentSymbol#range`
+ */
+
+ lsRange targetSelectionRange;
+
+ MAKE_SWAP_METHOD(LocationLink, originSelectionRange, targetUri, targetRange, targetSelectionRange);
+};
+MAKE_REFLECT_STRUCT(LocationLink, originSelectionRange, targetUri, targetRange, targetSelectionRange); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lru_cache.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lru_cache.h
new file mode 100644
index 0000000000..f33bc5627a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lru_cache.h
@@ -0,0 +1,151 @@
+#pragma once
+
+#include <algorithm>
+#include <cassert>
+#include <limits>
+#include <memory>
+#include <vector>
+
+// Cache that evicts old entries which have not been used recently. Implemented
+// using array/linear search so this works well for small array sizes.
+template <typename TKey, typename TValue>
+struct LruCache {
+ explicit LruCache(int max_entries);
+
+ // Fetches an entry for |key|. If it does not exist, |allocator| will be
+ // invoked to create one.
+ template <typename TAllocator>
+ TValue Get(const TKey& key, TAllocator allocator);
+ // Returns true if there is an entry for |key|.
+ bool Has(const TKey& key);
+ // Fetches the entry for |filename| and updates it's usage so it is less
+ // likely to be evicted.
+ bool TryGet(const TKey& key, TValue* dest);
+ // TryGetEntry, except the entry is removed from the cache.
+ bool TryTake(const TKey& key, TValue* dest);
+ // Inserts an entry. Evicts the oldest unused entry if there is no space.
+ void Insert(const TKey& key, const TValue& value);
+
+ // Call |func| on existing entries. If |func| returns false iteration
+ // terminates early.
+ template <typename TFunc>
+ void IterateValues(TFunc func);
+
+ // Empties the cache
+ void Clear(void);
+
+ private:
+ // There is a global score counter, when we access an element we increase
+ // its score to the current global value, so it has the highest overall
+ // score. This means that the oldest/least recently accessed value has the
+ // lowest score.
+ //
+ // There is a bit of special logic to handle score overlow.
+ struct Entry {
+ uint32_t score = 0;
+ TKey key;
+ TValue value;
+ bool operator<(const Entry& other) const { return score < other.score; }
+ };
+
+ void IncrementScore();
+
+ std::vector<Entry> entries_;
+ int max_entries_ = 1;
+ uint32_t next_score_ = 0;
+};
+
+template <typename TKey, typename TValue>
+LruCache<TKey, TValue>::LruCache(int max_entries) : max_entries_(max_entries) {
+ assert(max_entries > 0);
+}
+
+template <typename TKey, typename TValue>
+template <typename TAllocator>
+TValue LruCache<TKey, TValue>::Get(const TKey& key, TAllocator allocator) {
+ for (Entry& entry : entries_) {
+ if (entry.key == key)
+ return entry.value;
+ }
+
+ auto result = allocator();
+ Insert(key, result);
+ return result;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::Has(const TKey& key) {
+ for (Entry& entry : entries_) {
+ if (entry.key == key)
+ return true;
+ }
+ return false;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::TryGet(const TKey& key, TValue* dest) {
+ // Assign new score.
+ for (Entry& entry : entries_) {
+ if (entry.key == key) {
+ entry.score = next_score_;
+ IncrementScore();
+ if (dest)
+ *dest = entry.value;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::TryTake(const TKey& key, TValue* dest) {
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ if (entries_[i].key == key) {
+ if (dest)
+ *dest = entries_[i].value;
+ entries_.erase(entries_.begin() + i);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::Insert(const TKey& key, const TValue& value) {
+ if ((int)entries_.size() >= max_entries_)
+ entries_.erase(std::min_element(entries_.begin(), entries_.end()));
+
+ Entry entry;
+ entry.score = next_score_;
+ IncrementScore();
+ entry.key = key;
+ entry.value = value;
+ entries_.push_back(entry);
+}
+
+template <typename TKey, typename TValue>
+template <typename TFunc>
+void LruCache<TKey, TValue>::IterateValues(TFunc func) {
+ for (Entry& entry : entries_) {
+ if (!func(entry.value))
+ break;
+ }
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::IncrementScore() {
+ // Overflow.
+ if (++next_score_ == 0) {
+ std::sort(entries_.begin(), entries_.end());
+ for (Entry& entry : entries_)
+ entry.score = next_score_++;
+ }
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::Clear(void) {
+ entries_.clear();
+ next_score_ = 0;
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsAny.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsAny.h
new file mode 100644
index 0000000000..3335aa86dc
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsAny.h
@@ -0,0 +1,159 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <string>
+#include "LibLsp/JsonRpc/message.h"
+namespace lsp
+{
+ struct Any
+ {
+ //! Type of JSON value
+ enum Type {
+ kUnKnown=-1,
+ kNullType = 0, //!< null
+ kFalseType = 1, //!< false
+ kTrueType = 2, //!< true
+ kObjectType = 3, //!< object
+ kArrayType = 4, //!< array
+ kStringType = 5, //!< string
+ kNumberType = 6 //!< number
+ };
+
+
+
+ template <typename T>
+ bool Get(T& value);
+
+ template <typename T>
+ void Set(T& value);
+
+ int GuessType();
+ int GetType();
+
+ void Set(std::unique_ptr<LspMessage> value);
+
+ void SetJsonString(std::string&& _data, Type _type);
+
+ void SetJsonString(const std::string& _data, Type _type);
+
+ const std::string& Data()const
+ {
+ return data;
+ }
+
+ void swap(Any& arg) noexcept;
+
+ /*
+ *Example for GetFromMap
+ struct A{
+ std::string visitor;
+ bool verbose;
+ }
+ REFLECT_MAP_TO_STRUCT(A,visitor,verbose)
+
+ std::string data = "{\"visitor\":\"default\",\"verbose\":\"true\"};
+ lsp:Any any;
+ any.SetJsonString(data, static_cast<lsp::Any::Type>(-1));
+ A a_object;
+ any.GetFromMap(a_object);
+ */
+ template <typename T>
+ bool GetFromMap(T& value);
+
+
+ template <typename T>
+ bool GetForMapHelper(T& value);
+ bool GetForMapHelper(std::string& value);
+ bool GetForMapHelper(boost::optional<std::string>& value);
+ private:
+ std::unique_ptr<Reader> GetReader();
+ std::unique_ptr<Writer> GetWriter() const;
+ void SetData(std::unique_ptr<Writer>&);
+
+ std::string data;
+ int jsonType = kUnKnown;
+
+ };
+
+};
+
+
+extern void Reflect(Reader& visitor, lsp::Any& value);
+extern void Reflect(Writer& visitor, lsp::Any& value);
+
+template <typename T>
+void ReflectMember(std::map < std::string, lsp::Any>& visitor, const char* name, T& value) {
+
+ auto it = visitor.find(name);
+ if (it != visitor.end())
+ {
+ it->second.GetForMapHelper(value);
+ }
+}
+template <typename T>
+void ReflectMember(std::map < std::string, std::string>& visitor, const char* name, T& value) {
+
+ auto it = visitor.find(name);
+ if (it != visitor.end())
+ {
+ lsp::Any any;
+ any.SetJsonString(it->second, static_cast<lsp::Any::Type>(-1));
+ any.Get(value);
+ }
+}
+
+#define REFLECT_MAP_TO_STRUCT(type, ...) \
+ template <typename TVisitor> \
+ void ReflectMap(TVisitor& visitor, type& value) { \
+ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \
+ }
+
+
+namespace lsp
+{
+ template <typename T>
+ bool Any::Get(T& value)
+ {
+ const auto visitor = GetReader();
+ Reflect(*visitor, value);
+ return true;
+ }
+
+ template <typename T>
+ void Any::Set(T& value)
+ {
+ auto visitor = GetWriter();
+ Reflect(*visitor, value);
+ SetData(visitor);
+ }
+
+ template <typename T>
+ bool Any::GetFromMap(T& value)
+ {
+ const auto visitor = GetReader();
+ std::map < std::string, lsp::Any> _temp;
+ Reflect(*visitor, _temp);
+ ReflectMap(_temp, value);
+ return true;
+ }
+
+ template <typename T>
+ bool Any::GetForMapHelper(T& value)
+ {
+ jsonType = GetType();
+ if (jsonType == kStringType)
+ {
+ auto copy = data;
+ copy.erase(copy.find_last_not_of('"') + 1);
+ copy.erase(0, copy.find_first_not_of('"'));
+ lsp::Any any;
+ any.SetJsonString(copy, kUnKnown);
+ any.Get(value);
+ }
+ else
+ {
+ Get(value);
+ }
+ return true;
+ }
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsCodeAction.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsCodeAction.h
new file mode 100644
index 0000000000..06a14f1540
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsCodeAction.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+
+
+#include <string>
+#include <vector>
+#include "lsPosition.h"
+#include "lsWorkspaceEdit.h"
+#include "lsp_diagnostic.h"
+#include "lsCommand.h"
+
+struct CodeAction
+{
+ /**
+ * A short, human-readable, title for this code action.
+ */
+
+ std::string title;
+
+ /**
+ * The kind of the code action.
+ *
+ * Used to filter code actions.
+ */
+ boost::optional < std::string> kind;
+
+ /**
+ * The diagnostics that this code action resolves.
+ */
+ boost::optional < std::vector<lsDiagnostic>> diagnostics;
+
+ /**
+ * The workspace edit this code action performs.
+ */
+ boost::optional < lsWorkspaceEdit >edit;
+
+ /**
+ * A command this code action executes. If a code action
+ * provides a edit and a command, first the edit is
+ * executed and then the command.
+ */
+ boost::optional< lsCommandWithAny > command;
+
+ MAKE_SWAP_METHOD(CodeAction, title, kind, diagnostics, edit, command)
+};
+MAKE_REFLECT_STRUCT(CodeAction, title, kind, diagnostics, edit, command)
+struct TextDocumentCodeAction
+
+{
+
+ typedef std::pair<boost::optional<lsCommandWithAny>, boost::optional<CodeAction> > Either;
+
+};
+
+
+extern void Reflect(Reader& visitor, TextDocumentCodeAction::Either& value); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsCommand.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsCommand.h
new file mode 100644
index 0000000000..94307f1479
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsCommand.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+
+
+#include <string>
+#include <vector>
+#include "lsAny.h"
+//
+//Represents a reference to a command.Provides a title which will be used to represent a command in the UI.
+//Commands are identified by a string identifier.
+//The recommended way to handle commands is to implement their execution on the server side
+//if the clientand server provides the corresponding capabilities.Alternatively the tool
+//extension code could handle the command.The protocol currently doesn¡¯t specify a set of well - known commands.
+template <typename AnyArray>
+struct lsCommand {
+ // Title of the command (ie, 'save')
+ std::string title;
+ // Actual command identifier.
+ std::string command;
+ // Arguments to run the command with.
+ // **NOTE** This must be serialized as an array. Use
+ // MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY.
+ boost::optional<AnyArray> arguments;
+
+ void swap(lsCommand<AnyArray>& arg) noexcept
+ {
+ title.swap(arg.title);
+ command.swap(arg.command);
+ arguments.swap(arg.arguments);
+ }
+};
+template <typename TVisitor, typename T>
+void Reflect(TVisitor& visitor, lsCommand<T>& value) {
+ REFLECT_MEMBER_START();
+ REFLECT_MEMBER(title);
+ REFLECT_MEMBER(command);
+ REFLECT_MEMBER(arguments);
+ REFLECT_MEMBER_END();
+}
+
+
+using lsCommandWithAny = lsCommand< std::vector<lsp::Any>>;
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsDocumentUri.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsDocumentUri.h
new file mode 100644
index 0000000000..5d24f59e3a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsDocumentUri.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "LibLsp/JsonRpc/serializer.h"
+#include <string>
+struct lsDocumentUri {
+ static lsDocumentUri FromPath(const AbsolutePath& path);
+
+ lsDocumentUri();
+
+ lsDocumentUri(const AbsolutePath& path);
+ lsDocumentUri(const lsDocumentUri& other);;
+ bool operator==(const lsDocumentUri& other) const;
+ bool operator==(const std::string& other) const;
+ void SetPath(const AbsolutePath& path);
+ std::string GetRawPath() const;
+ AbsolutePath GetAbsolutePath() const;
+
+
+ std::string raw_uri_;
+ void swap(lsDocumentUri& arg) noexcept
+ {
+ raw_uri_.swap(arg.raw_uri_);
+ }
+};
+extern void Reflect(Writer& visitor, lsDocumentUri& value);
+extern void Reflect(Reader& visitor, lsDocumentUri& value);
+extern std::string make_file_scheme_uri(const std::string& absolute_path);
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsFormattingOptions.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsFormattingOptions.h
new file mode 100644
index 0000000000..a92df9b077
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsFormattingOptions.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+struct lsFormattingOptions {
+ struct KeyData {
+ boost::optional<bool> _boolean;
+ boost::optional<int32_t> _integer;
+ boost::optional<std::string> _string;
+ };
+
+ // Size of a tab in spaces.
+ int tabSize =4;
+ // Prefer spaces over tabs.
+ bool insertSpaces = true;
+
+ /**
+ * Trim trailing whitespace on a line.
+ *
+ * @since 3.15.0
+ */
+ boost::optional<bool> trimTrailingWhitespace;
+
+ /**
+ * Insert a newline character at the end of the file if one does not exist.
+ *
+ * @since 3.15.0
+ */
+ boost::optional<bool> insertFinalNewline;
+
+ /**
+ * Trim all newlines after the final newline at the end of the file.
+ *
+ * @since 3.15.0
+ */
+ boost::optional<bool> trimFinalNewlines;
+ boost::optional<KeyData> key;
+ MAKE_SWAP_METHOD(lsFormattingOptions, tabSize, insertSpaces, trimTrailingWhitespace, insertFinalNewline, trimFinalNewlines, key)
+};
+MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces, trimTrailingWhitespace, insertFinalNewline, trimFinalNewlines, key);
+
+extern void Reflect(Reader& visitor, lsFormattingOptions::KeyData& value);
+extern void Reflect(Writer& visitor, lsFormattingOptions::KeyData& value); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsMarkedString.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsMarkedString.h
new file mode 100644
index 0000000000..9191aa66d1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsMarkedString.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+#include <string>
+#include <vector>
+
+
+// MarkedString can be used to render human readable text. It is either a
+// markdown string or a code-block that provides a language and a code snippet.
+// The language identifier is sematically equal to the optional language
+// identifier in fenced code blocks in GitHub issues. See
+// https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
+//
+// The pair of a language and a value is an equivalent to markdown:
+// ```${language}
+// ${value}
+// ```
+//
+// Note that markdown strings will be sanitized - that means html will be
+// escaped.
+struct lsMarkedString {
+ boost::optional<std::string> language;
+ std::string value;
+};
+
+struct MarkupContent {
+ /**
+ * The type of the Markup.
+ */
+
+ std::string kind;
+
+ /**
+ * The content itself.
+ */
+
+ std::string value;
+
+ MAKE_SWAP_METHOD(MarkupContent, kind, value);
+};
+MAKE_REFLECT_STRUCT(MarkupContent,kind,value);
+
+void Reflect(Writer& visitor, lsMarkedString& value);
+void Reflect(Reader& visitor, lsMarkedString& value);
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsPosition.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsPosition.h
new file mode 100644
index 0000000000..8c2106e16e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsPosition.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+
+
+#include <string>
+#include <vector>
+
+//Position in a text document expressed as zero - based line and zero - based character offset.
+//A position is between two characters like an ¡®insert¡¯ cursor in a editor.Special values like
+//for example - 1 to denote the end of a line are not supported.
+struct lsPosition {
+ lsPosition();
+ lsPosition(int line, int character);
+
+ bool operator==(const lsPosition& other) const;
+ bool operator<(const lsPosition& other) const;
+
+ std::string ToString() const;
+
+ /**
+ * Line position in a document (zero-based).
+ */
+ // Note: these are 0-based.
+ unsigned line = 0;
+ /**
+ * Character offset on a line in a document (zero-based). Assuming that
+ * the line is represented as a string, the `character` value represents
+ * the gap between the `character` and `character + 1`.
+ *
+ * If the character value is greater than the line length it defaults back
+ * to the line length.
+ */
+ unsigned character = 0;
+ static const lsPosition kZeroPosition;
+
+ MAKE_SWAP_METHOD(lsPosition, line, character)
+};
+MAKE_REFLECT_STRUCT(lsPosition, line, character); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsRange.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsRange.h
new file mode 100644
index 0000000000..6cc01e37a7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsRange.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+
+
+#include <string>
+#include <vector>
+#include "lsPosition.h"
+//A range in a text document expressed as(zero - based) startand end positions.
+//A range is comparable to a selection in an editor.Therefore the end position is exclusive.
+//If you want to specify a range that contains a line including the line ending character(s)
+//then use an end position denoting the start of the next line.
+struct lsRange {
+ lsRange();
+ lsRange(lsPosition start, lsPosition end);
+
+ bool operator==(const lsRange& other) const;
+ bool operator<(const lsRange& other) const;
+ /**
+ * The range's start position.
+ */
+ lsPosition start;
+ /**
+ * The range's end position.
+ */
+ lsPosition end;
+ std::string ToString()const;
+ MAKE_SWAP_METHOD(lsRange, start, end)
+};
+
+MAKE_REFLECT_STRUCT(lsRange, start, end) \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsResponseError.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsResponseError.h
new file mode 100644
index 0000000000..6146d6188f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsResponseError.h
@@ -0,0 +1,117 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <sstream>
+#include "LibLsp/lsp/lsAny.h"
+
+enum class lsErrorCodes:int32_t {
+ // Defined by JSON RPC
+ ParseError = -32700,
+ InvalidRequest = -32600,
+ MethodNotFound = -32601,
+ InvalidParams = -32602,
+ InternalError = -32603,
+
+ /**
+ * This is the start range of JSON RPC reserved error codes.
+ * It doesn't denote a real error code. No LSP error codes should
+ * be defined between the start and end range. For backwards
+ * compatibility the `ServerNotInitialized` and the `UnknownErrorCode`
+ * are left in the range.
+ *
+ * @since 3.16.0
+ */
+ jsonrpcReservedErrorRangeStart = -32099,
+ /** @deprecated use jsonrpcReservedErrorRangeStart */
+ serverErrorStart = jsonrpcReservedErrorRangeStart,
+
+ /**
+ * This is the start range of JSON RPC reserved error codes.
+ * It doesn't denote a real error code.
+ *
+ * @since 3.16.0
+ */
+ jsonrpcReservedErrorRangeEnd = -32000,
+ /** @deprecated use jsonrpcReservedErrorRangeEnd */
+ serverErrorEnd = jsonrpcReservedErrorRangeEnd,
+
+ /**
+ * Error code indicating that a server received a notification or
+ * request before the server has received the `initialize` request.
+ */
+ ServerNotInitialized = -32002,
+ UnknownErrorCode = -32001,
+
+ /**
+ * This is the start range of LSP reserved error codes.
+ * It doesn't denote a real error code.
+ *
+ * @since 3.16.0
+ */
+ lspReservedErrorRangeStart= -32899,
+
+ /**
+ * The server cancelled the request. This error code should
+ * only be used for requests that explicitly support being
+ * server cancellable.
+ *
+ * @since 3.17.0
+ */
+ ServerCancelled = -32802,
+
+ /**
+ * The server detected that the content of a document got
+ * modified outside normal conditions. A server should
+ * NOT send this error code if it detects a content change
+ * in it unprocessed messages. The result even computed
+ * on an older state might still be useful for the client.
+ *
+ * If a client decides that a result is not of any use anymore
+ * the client should cancel the request.
+ */
+ ContentModified = -32801,
+
+ /**
+ * The client has canceled a request and a server as detected
+ * the cancel.
+ */
+ RequestCancelled = -32800,
+
+ /**
+ * This is the end range of LSP reserved error codes.
+ * It doesn't denote a real error code.
+ *
+ * @since 3.16.0
+ */
+ lspReservedErrorRangeEnd = -32800,
+
+
+
+};
+MAKE_REFLECT_TYPE_PROXY(lsErrorCodes);
+struct lsResponseError {
+ lsResponseError(): code(lsErrorCodes::UnknownErrorCode)
+ {
+ }
+
+ /**
+ * A number indicating the error type that occurred.
+ */
+ lsErrorCodes code;
+ // Short description.
+ /**
+ * A string providing a short description of the error.
+ */
+ std::string message;
+
+ /**
+ * A primitive or structured value that contains additional
+ * information about the error. Can be omitted.
+ */
+ boost::optional<lsp::Any> data;
+ std::string ToString();
+ void Write(Writer& visitor);
+
+ MAKE_SWAP_METHOD(lsResponseError, code, message, data)
+};
+MAKE_REFLECT_STRUCT(lsResponseError, code, message, data) \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentEdit.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentEdit.h
new file mode 100644
index 0000000000..0bab8bc3d8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentEdit.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <vector>
+#include "LibLsp/JsonRpc/message.h"
+#include "lsVersionedTextDocumentIdentifier.h"
+#include "lsTextEdit.h"
+
+
+struct lsTextDocumentEdit {
+ // The text document to change.
+ lsVersionedTextDocumentIdentifier textDocument;
+
+ /**
+ * The edits to be applied.
+ *
+ * @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
+ * client capability `workspace.workspaceEdit.changeAnnotationSupport`
+ */
+ // The edits to be applied.
+ std::vector< lsAnnotatedTextEdit > edits;
+ MAKE_SWAP_METHOD(lsTextDocumentEdit, textDocument, edits);
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentEdit, textDocument, edits); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentIdentifier.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentIdentifier.h
new file mode 100644
index 0000000000..bb316eae5a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentIdentifier.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include "lsDocumentUri.h"
+//Text documents are identified using a URI.On the protocol level,
+//URIs are passed as strings.The corresponding JSON structure looks like this:
+struct lsTextDocumentIdentifier {
+ /**
+ * The text document's URI.
+ */
+ lsDocumentUri uri;
+ MAKE_SWAP_METHOD(lsTextDocumentIdentifier, uri)
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentIdentifier, uri) \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentItem.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentItem.h
new file mode 100644
index 0000000000..4d9b4ccc9f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentItem.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <string>
+#include <vector>
+#include "lsDocumentUri.h"
+
+//An item to transfer a text document from the client to the server.
+struct lsTextDocumentItem {
+ // The text document's URI.
+ lsDocumentUri uri;
+
+ // The text document's language identifier.
+ std::string languageId;
+
+ // The version number of this document (it will strictly increase after each
+ // change, including undo/redo).
+ int version = 0;
+
+ // The content of the opened text document.
+ std::string text;
+
+ MAKE_SWAP_METHOD(lsTextDocumentItem, uri, languageId, version, text)
+};
+
+MAKE_REFLECT_STRUCT(lsTextDocumentItem, uri, languageId, version, text) \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentPositionParams.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentPositionParams.h
new file mode 100644
index 0000000000..52d291351e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextDocumentPositionParams.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/message.h"
+
+#include "lsTextDocumentIdentifier.h"
+#include "lsPosition.h"
+
+/**
+ * A parameter literal used in requests to pass a text document and a position inside that document.
+ */
+struct lsTextDocumentPositionParams {
+ // The text document.
+ lsTextDocumentIdentifier textDocument;
+
+ // The position inside the text document.
+ lsPosition position;
+
+ /**
+ * Legacy property to support protocol version 1.0 requests.
+ */
+ boost::optional<lsDocumentUri> uri;
+
+ MAKE_SWAP_METHOD(lsTextDocumentPositionParams, textDocument, position, uri);
+
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentPositionParams, textDocument, position, uri);
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextEdit.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextEdit.h
new file mode 100644
index 0000000000..8785e0dcbc
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsTextEdit.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+
+
+#include <string>
+#include "lsRange.h"
+
+
+//Since 3.16.0 there is also the concept of an annotated text edit which supports to add an annotation to a text edit.
+//The annotation can add information describing the change to the text edit.
+/**
+ * Additional information that describes document changes.
+ *
+ * @since 3.16.0
+ */
+struct lsChangeAnnotation
+{
+ /**
+ * A human-readable string describing the actual change. The string
+ * is rendered prominent in the user interface.
+ */
+ std::string label;
+
+ /**
+ * A flag which indicates that user confirmation is needed
+ * before applying the change.
+ */
+ boost::optional<bool> needsConfirmation;
+
+ /**
+ * A human-readable string which is rendered less prominent in
+ * the user interface.
+ */
+ boost::optional < std::string > description;
+ MAKE_REFLECT_STRUCT(lsChangeAnnotation, label, needsConfirmation, description)
+};
+MAKE_REFLECT_STRUCT(lsChangeAnnotation, label, needsConfirmation, description)
+
+
+//Usually clients provide options to group the changes along the annotations they are associated with.
+//To support this in the protocol an edit or resource operation refers to a change annotation
+//using an identifier and not the change annotation literal directly.This allows servers to use
+//the identical annotation across multiple edits or resource operations which then allows clients
+//to group the operations under that change annotation.The actual change annotations together with
+//their identifers are managed by the workspace edit via the new property changeAnnotations.
+
+
+
+/**
+ * An identifier referring to a change annotation managed by a workspace
+ * edit.
+ *
+ * @since 3.16.0.
+ */
+using lsChangeAnnotationIdentifier = std::string;
+/**
+ * A special text edit with an additional change annotation.
+ *
+ * @since 3.16.0.
+ */
+
+
+//A textual edit applicable to a text document.
+struct lsTextEdit {
+ // The range of the text document to be manipulated. To insert
+ // text into a document create a range where start === end.
+ lsRange range;
+
+ // The string to be inserted. For delete operations use an
+ // empty string.
+ std::string newText;
+
+ /**
+ * The actual annotation identifier.
+ */
+ boost::optional<lsChangeAnnotationIdentifier> annotationId;
+
+
+ bool operator==(const lsTextEdit& that);
+ std::string ToString() const;
+ MAKE_SWAP_METHOD(lsTextEdit, range, newText, annotationId)
+};
+MAKE_REFLECT_STRUCT(lsTextEdit, range, newText, annotationId)
+
+using lsAnnotatedTextEdit = lsTextEdit;
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h
new file mode 100644
index 0000000000..8a858053b1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+
+#include "LibLsp/JsonRpc/message.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+struct lsVersionedTextDocumentIdentifier
+{
+ lsDocumentUri uri;
+ // The version number of this document. number | null
+ boost::optional<int> version;
+
+ lsTextDocumentIdentifier AsTextDocumentIdentifier() const;
+
+ MAKE_SWAP_METHOD(lsVersionedTextDocumentIdentifier, uri, version)
+};
+MAKE_REFLECT_STRUCT(lsVersionedTextDocumentIdentifier, uri, version)
+
+/**
+ * The version number of this document. If an optional versioned text document
+ * identifier is sent from the server to the client and the file is not
+ * open in the editor (the server has not received an open notification
+ * before) the server can send `null` to indicate that the version is
+ * known and the content on disk is the master (as specified with document
+ * content ownership).
+ *
+ * The version number of a document will increase after each change,
+ * including undo/redo. The number doesn't need to be consecutive.
+ */
+using lsOptionalVersionedTextDocumentIdentifier = lsVersionedTextDocumentIdentifier; \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsWorkspaceEdit.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsWorkspaceEdit.h
new file mode 100644
index 0000000000..c7fb73930a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsWorkspaceEdit.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/serializer.h"
+#include <vector>
+#include "lsTextDocumentEdit.h"
+#include "LibLsp/lsp/ResourceOperation.h"
+#include "lsAny.h"
+
+//A workspace edit represents changes to many resources managed in the workspace.
+//The edit should either provide changes or documentChanges.
+//If the client can handle versioned document edits and if documentChanges are present, the latter are preferred over changes.
+
+//Since version 3.13.0 a workspace edit can contain resource operations(create, delete or rename files and folders) as well.
+//If resource operations are present clients need to execute the operations in the order in which they are provided.
+//So a workspace edit for example can consist of the following two changes : (1) create file a.txt and (2) a text document edit which insert text into file a.
+//txt.An invalid sequence(e.g. (1) delete file a.txt and (2) insert text into file a.txt) will cause failure of the operation.
+//How the client recovers from the failure is described by the client capability : workspace.workspaceEdit.failureHandling
+
+
+
+struct lsChangeAnnotations
+{
+ lsChangeAnnotation id;
+ MAKE_SWAP_METHOD(lsChangeAnnotations, id)
+};
+MAKE_REFLECT_STRUCT(lsChangeAnnotations, id)
+struct lsWorkspaceEdit {
+ // Holds changes to existing resources.
+ // changes ? : { [uri:string]: TextEdit[]; };
+ // std::unordered_map<lsDocumentUri, std::vector<lsTextEdit>> changes;
+
+ // An array of `TextDocumentEdit`s to express changes to specific a specific
+ // version of a text document. Whether a client supports versioned document
+ // edits is expressed via `WorkspaceClientCapabilites.versionedWorkspaceEdit`.
+ //
+ boost::optional< std::map<std::string, std::vector<lsTextEdit> > > changes;
+ typedef std::pair < boost::optional<lsTextDocumentEdit>, boost::optional<lsp::Any> > Either;
+
+ boost::optional < std::vector< Either > > documentChanges;
+ /**
+ * A map of change annotations that can be referenced in
+ * `AnnotatedTextEdit`s or create, rename and delete file / folder
+ * operations.
+ *
+ * Whether clients honor this property depends on the client capability
+ * `workspace.changeAnnotationSupport`.
+ *
+ * @since 3.16.0
+ */
+ boost::optional< lsChangeAnnotations > changeAnnotations;
+
+ MAKE_SWAP_METHOD(lsWorkspaceEdit, changes, documentChanges, changeAnnotations)
+};
+MAKE_REFLECT_STRUCT(lsWorkspaceEdit, changes, documentChanges, changeAnnotations)
+
+extern void Reflect(Reader& visitor, lsWorkspaceEdit::Either& value);
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsp.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp.cpp
new file mode 100644
index 0000000000..81bf34ba3a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp.cpp
@@ -0,0 +1,1087 @@
+
+
+#include "lru_cache.h"
+
+
+#include <rapidjson/writer.h>
+
+
+#include <stdio.h>
+#include <iostream>
+#include "location_type.h"
+#include "out_list.h"
+#include "lsTextDocumentIdentifier.h"
+#include "lsVersionedTextDocumentIdentifier.h"
+#include "lsResponseError.h"
+#include "lsPosition.h"
+#include "lsTextEdit.h"
+#include "lsMarkedString.h"
+#include "lsWorkspaceEdit.h"
+#include "textDocument/code_action.h"
+#include "textDocument/document_symbol.h"
+#include "extention/jdtls/codeActionResult.h"
+
+#include "textDocument/selectionRange.h"
+#include "AbsolutePath.h"
+
+#ifdef _WIN32
+#include <Windows.h>
+#else
+#include <climits>
+#include <cstdlib>
+#endif
+
+#include "Directory.h"
+#include "lsFormattingOptions.h"
+#include "LibLsp/JsonRpc/json.h"
+#include "language/language.h"
+#include "network/uri/uri_builder.hpp"
+#include "lsp_completion.h"
+#include "utils.h"
+#include "client/registerCapability.h"
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+// namespace
+
+
+
+lsTextDocumentIdentifier
+lsVersionedTextDocumentIdentifier::AsTextDocumentIdentifier() const {
+ lsTextDocumentIdentifier result;
+ result.uri = uri;
+ return result;
+}
+
+
+lsPosition::lsPosition() {}
+lsPosition::lsPosition(int line, int character)
+ : line(line), character(character) {}
+
+bool lsPosition::operator==(const lsPosition& other) const {
+ return line == other.line && character == other.character;
+}
+
+bool lsPosition::operator<(const lsPosition& other) const {
+ return line != other.line ? line < other.line : character < other.character;
+}
+
+std::string lsPosition::ToString() const {
+ return std::to_string(line) + ":" + std::to_string(character);
+}
+const lsPosition lsPosition::kZeroPosition = lsPosition();
+
+lsRange::lsRange() {}
+lsRange::lsRange(lsPosition start, lsPosition end) : start(start), end(end) {}
+
+bool lsRange::operator==(const lsRange& o) const {
+ return start == o.start && end == o.end;
+}
+
+bool lsRange::operator<(const lsRange& o) const {
+ return !(start == o.start) ? start < o.start : end < o.end;
+}
+
+std::string lsRange::ToString() const
+{
+ std::stringstream ss;
+ ss << "start:" << start.ToString() << std::endl;
+ ss << "end" << end.ToString() << std::endl;
+ return ss.str();
+}
+
+lsLocation::lsLocation() {}
+lsLocation::lsLocation(lsDocumentUri uri, lsRange range)
+ : uri(uri), range(range) {}
+
+bool lsLocation::operator==(const lsLocation& o) const {
+ return uri == o.uri && range == o.range;
+}
+
+bool lsLocation::operator<(const lsLocation& o) const {
+ return std::make_tuple(uri.raw_uri_, range) <
+ std::make_tuple(o.uri.raw_uri_, o.range);
+}
+
+bool lsTextEdit::operator==(const lsTextEdit& that) {
+ return range == that.range && newText == that.newText;
+}
+
+std::string lsTextEdit::ToString() const
+{
+ std::stringstream ss;
+ ss << "Range:" << range.ToString() << std::endl;
+ ss << "newText:" << newText << std::endl;
+ return ss.str();
+}
+
+void Reflect(Writer& visitor, lsMarkedString& value) {
+ // If there is a language, emit a `{language:string, value:string}` object. If
+ // not, emit a string.
+ if (value.language) {
+ REFLECT_MEMBER_START();
+ REFLECT_MEMBER(language);
+ REFLECT_MEMBER(value);
+ REFLECT_MEMBER_END();
+ } else {
+ Reflect(visitor, value.value);
+ }
+}
+
+void Reflect(Reader& visitor, lsMarkedString& value)
+{
+ REFLECT_MEMBER_START();
+ REFLECT_MEMBER(language);
+ REFLECT_MEMBER(value);
+ REFLECT_MEMBER_END();
+}
+
+ void Reflect(Reader& visitor, LocationListEither::Either& value)
+{
+ if(!visitor.IsArray())
+ {
+ throw std::invalid_argument("Rsp_LocationListEither::Either& value is not array");
+ }
+ auto data = ((JsonReader&)visitor).m_->GetArray();
+ if (data.Size() && data[0].HasMember("originSelectionRange"))
+ {
+ Reflect(visitor, value.second);
+ }
+ else {
+ Reflect(visitor, value.first);
+ }
+
+}
+
+ void Reflect(Writer& visitor, LocationListEither::Either& value)
+{
+ if (value.first)
+ {
+ Reflect(visitor, value.first.value());
+ }
+ else if (value.second)
+ {
+ Reflect(visitor, value.second.value());
+ }
+}
+
+
+void Reflect(Reader& visitor, TextDocumentCodeAction::Either& value)
+{
+
+
+ if(visitor.HasMember("command"))
+ {
+ if(visitor["command"]->IsString())
+ {
+ Reflect(visitor, value.first);
+ }
+ else
+ {
+ Reflect(visitor, value.second);
+ }
+ }
+ else
+ {
+ if (visitor.HasMember("diagnostics") || visitor.HasMember("edit"))
+ {
+ Reflect(visitor, value.second);
+ }
+ else
+ {
+ Reflect(visitor, value.first);
+ }
+ }
+
+}
+
+
+void Reflect(Reader& visitor, lsWorkspaceEdit::Either& value)
+{
+
+
+ if(visitor.HasMember("textDocument"))
+ {
+ Reflect(visitor, value.first);
+ }
+ else
+ {
+ Reflect(visitor, value.second);
+ }
+}
+ResourceOperation* GetResourceOperation(lsp::Any& lspAny)
+{
+ rapidjson::Document document;
+ auto& data = lspAny.Data();
+ document.Parse(data.c_str(), data.length());
+ if (document.HasParseError()) {
+ // ��ʾ
+ return nullptr;
+ }
+ auto find = document.FindMember("kind");
+
+ JsonReader visitor{ &document };
+ try
+ {
+ if (find->value == "create")
+ {
+ auto ptr = std::make_unique<lsCreateFile>();
+ auto temp = ptr.get();
+ Reflect(visitor, *temp);
+ return ptr.release();
+ }
+ else if (find->value == "rename")
+ {
+ auto ptr = std::make_unique<lsRenameFile>();
+ auto temp = ptr.get();
+ Reflect(visitor, *temp);
+ return ptr.release();
+ }
+ else if (find->value == "delete")
+ {
+
+ auto ptr = std::make_unique<lsDeleteFile>();
+ auto temp = ptr.get();
+ Reflect(visitor, *temp);
+ return ptr.release();
+ }
+ }
+ catch (std::exception&)
+ {
+
+ }
+ return nullptr;
+}
+
+ void Reflect(Writer& visitor, ResourceOperation* value)
+{
+
+ if(!value)
+ {
+ throw std::invalid_argument("ResourceOperation value is nullptr");
+ }
+ if (value->kind == "create")
+ {
+ auto temp = (lsCreateFile*)value;
+ Reflect(visitor, *temp);
+ }
+ else if (value->kind == "rename")
+ {
+ auto temp = (lsRenameFile*)value;
+ Reflect(visitor, *temp);
+ }
+ else if (value->kind == "delete")
+ {
+
+ auto temp = (lsDeleteFile*)value;
+ Reflect(visitor, *temp);
+ }
+
+}
+
+int lsp::Any::GuessType()
+{
+ if (!data.empty())
+ {
+ if (data == "null")
+ {
+ jsonType = rapidjson::kNullType;
+ }
+ else if (data == "true")
+ {
+ jsonType = rapidjson::kTrueType;
+ }
+ else if(data == "false")
+ {
+ jsonType = rapidjson::kFalseType;
+ }
+ else if (data[0] == '{')
+ {
+ jsonType = rapidjson::kObjectType;
+ }
+ else if (data[0] == '[')
+ {
+ if (data.size() >= 2 && data[1] == '{')
+ jsonType = rapidjson::kStringType;
+ else
+ jsonType = rapidjson::kArrayType;
+ }
+ else if (data[0] == '"')
+ {
+ jsonType = rapidjson::kStringType;
+ }
+ else
+ {
+ jsonType = rapidjson::kNumberType;
+ }
+ }
+ else
+ {
+ if (jsonType != kUnKnown)
+ return jsonType;
+ jsonType = rapidjson::kNullType;
+ }
+ return jsonType;
+}
+
+int lsp::Any::GetType()
+{
+ if (jsonType == Type::kUnKnown)
+ {
+ if (data.empty())
+ {
+ jsonType = rapidjson::kNullType;
+ return jsonType;
+ }
+ rapidjson::Document document;
+ document.Parse(data.c_str(), data.length());
+ if (document.HasParseError())
+ {
+ // ��ʾ
+ return jsonType;
+ }
+ jsonType = document.GetType();
+ }
+ return jsonType;
+}
+
+void lsp::Any::Set(std::unique_ptr<LspMessage> value)
+{
+ if (value)
+ {
+ jsonType = rapidjson::Type::kObjectType;
+ data = value->ToJson();
+ }
+ else
+ {
+ assert(false);
+ }
+}
+
+void lsp::Any::SetJsonString(std::string&& _data, Type _type)
+{
+ jsonType = _type;
+ data.swap(_data);
+ GetType();
+}
+
+void lsp::Any::SetJsonString(const std::string& _data, Type _type)
+{
+ jsonType = _type;
+ data = (_data);
+ GetType();
+}
+
+void lsp::Any::swap(Any& arg) noexcept
+{
+ data.swap(arg.data);
+ const int temp = jsonType;
+ jsonType = arg.jsonType;
+ arg.jsonType = temp;
+}
+
+class JsonReaderForAny : public JsonReader
+{
+public:
+ JsonReaderForAny()
+ : JsonReader(&document)
+ {
+ }
+ rapidjson::Document document;
+};
+
+bool lsp::Any::GetForMapHelper(std::string& value)
+{
+ return Get(value);
+}
+
+bool lsp::Any::GetForMapHelper(boost::optional<std::string>& value)
+{
+ return Get(value);
+}
+
+std::unique_ptr<Reader> lsp::Any::GetReader()
+{
+ auto reader = new JsonReaderForAny();
+ std::unique_ptr<Reader> ret(reader);
+ reader->document.Parse(data.c_str(), data.length());
+ if (reader->document.HasParseError())
+ {
+ return {};
+ }
+ if (jsonType == kUnKnown)
+ {
+ jsonType = reader->document.GetType();
+ }
+ return (ret);
+}
+
+class JsonWriterForAny : public JsonWriter
+{
+public:
+ rapidjson::StringBuffer output;
+ rapidjson::Writer<rapidjson::StringBuffer> writer;
+ JsonWriterForAny():JsonWriter(&writer), writer(output)
+ {
+
+ }
+};
+
+std::unique_ptr<Writer> lsp::Any::GetWriter() const
+{
+ return std::make_unique<JsonWriterForAny>();
+}
+
+void lsp::Any::SetData(std::unique_ptr<Writer>& writer)
+{
+ auto _temp = static_cast<JsonWriterForAny*>(writer.get());
+ data = _temp->output.GetString();
+ GuessType();
+}
+
+namespace
+{
+#if 0
+ rapidjson::Type convert(lsp::Any::Type type)
+ {
+ switch (type)
+ {
+ case lsp::Any::Type::kNullType:
+ return rapidjson::Type::kNullType;
+ case lsp::Any::Type::kFalseType:
+ return rapidjson::Type::kFalseType;
+ case lsp::Any::Type::kTrueType:
+ return rapidjson::Type::kTrueType;
+ case lsp::Any::Type::kObjectType:
+ return rapidjson::Type::kObjectType;
+ case lsp::Any::Type::kArrayType:
+ return rapidjson::Type::kArrayType;
+ case lsp::Any::Type::kStringType:
+ return rapidjson::Type::kStringType;
+ case lsp::Any::Type::kNumberType:
+ return rapidjson::Type::kNumberType;
+ default:
+ return rapidjson::Type::kNullType;
+ }
+ }
+#endif
+ lsp::Any::Type convert(rapidjson::Type type)
+ {
+ switch (type)
+ {
+ case rapidjson::Type::kNullType:
+ return lsp::Any::Type::kNullType;
+ case rapidjson::Type::kFalseType:
+ return lsp::Any::Type::kFalseType;
+ case rapidjson::Type::kTrueType:
+ return lsp::Any::Type::kTrueType;
+ case rapidjson::Type::kObjectType:
+ return lsp::Any::Type::kObjectType;
+ case rapidjson::Type::kArrayType:
+ return lsp::Any::Type::kArrayType;
+ case rapidjson::Type::kStringType:
+ return lsp::Any::Type::kStringType;
+ case rapidjson::Type::kNumberType:
+ return lsp::Any::Type::kNumberType;
+ default:
+ return lsp::Any::Type::kNullType;
+ }
+ }
+}
+
+void Reflect(Reader& visitor, lsp::Any& value)
+{
+
+ //if (visitor.IsNull()) {
+ // visitor.GetNull();
+ // value.SetJsonString("", rapidjson::Type::kNullType);
+ // return;
+ //}else
+ //{
+ //
+ //}
+ JsonReader& json_reader = reinterpret_cast<JsonReader&>(visitor);
+ value.SetJsonString(visitor.ToString(), convert(json_reader.m_->GetType()));
+}
+ void Reflect(Writer& visitor, lsp::Any& value)
+ {
+ JsonWriter& json_writer = reinterpret_cast<JsonWriter&>(visitor);
+ json_writer.m_->RawValue( value.Data().data(),value.Data().size(),static_cast<rapidjson::Type>(value.GetType()));
+
+ }
+ void Reflect(Reader& visitor, lsFormattingOptions::KeyData& value)
+{
+ if (visitor.IsBool())
+ {
+ Reflect(visitor, value._boolean);
+ }
+ else if (visitor.IsInt() || visitor.IsInt64() || visitor.IsUint64())
+ {
+ Reflect(visitor, value._integer);
+ }
+ else if(visitor.IsString())
+ {
+ Reflect(visitor, value._string);
+ }
+}
+ void Reflect(Writer& visitor, lsFormattingOptions::KeyData& value)
+{
+ if (value._boolean.has_value())
+ {
+ Reflect(visitor, value._boolean);
+ }
+ else if (value._integer.has_value())
+ {
+ Reflect(visitor, value._integer);
+ }
+ else if (value._string.has_value())
+ {
+ Reflect(visitor, value._string);
+ }
+}
+
+lsCreateFile::lsCreateFile()
+{
+ kind = "create";
+}
+
+lsDeleteFile::lsDeleteFile()
+{
+ kind = "delete";
+}
+
+lsRenameFile::lsRenameFile()
+{
+ kind = "rename";
+}
+
+
+void Reflect(Reader& visitor, boost::optional< SelectionRange* >& value)
+{
+ if (visitor.IsNull()) {
+ visitor.GetNull();
+ return;
+ }
+
+ SelectionRange* entry_value = nullptr;
+
+
+ std::unique_ptr<SelectionRange> ptr = std::make_unique<SelectionRange>();
+ SelectionRange* temp = ptr.get();
+ Reflect(visitor, *temp);
+
+ entry_value = ptr.release();
+ value = (entry_value);
+
+}
+void Reflect(Writer& visitor, SelectionRange* value)
+{
+
+ if (!value)
+ {
+ throw std::invalid_argument("ResourceOperation value is nullptr");
+ }
+
+ Reflect(visitor, *value);
+
+
+}
+
+ std::string make_file_scheme_uri(const std::string& absolute_path)
+{
+ network::uri_builder builder;
+ builder.scheme("file");
+ builder.host("");
+ builder.path(absolute_path);
+ return builder.uri().string();
+ //// lsDocumentUri uri;
+ //// uri.SetPath(absolute_path);
+ /// return uri.raw_uri_;
+}
+
+// static
+AbsolutePath AbsolutePath::BuildDoNotUse(const std::string& path) {
+ AbsolutePath p;
+ p.path = std::string(path);
+ return p;
+}
+
+
+AbsolutePath::AbsolutePath() {}
+
+
+
+AbsolutePath::operator std::string() const {
+ return path;
+}
+
+bool AbsolutePath::operator==(const AbsolutePath& rhs) const {
+ return path == rhs.path;
+}
+
+bool AbsolutePath::operator!=(const AbsolutePath& rhs) const {
+ return path != rhs.path;
+}
+
+bool AbsolutePath::operator<(const AbsolutePath& rhs) const
+{
+ return path < rhs.path;
+}
+
+bool AbsolutePath::operator>(const AbsolutePath& rhs) const
+{
+ return path > rhs.path;
+}
+
+void Reflect(Reader& visitor, AbsolutePath& value) {
+ value.path = visitor.GetString();
+}
+void Reflect(Writer& visitor, AbsolutePath& value) {
+ visitor.String(value.path.c_str(), value.path.length());
+}
+
+std::ostream& operator<<(std::ostream& out, const AbsolutePath& path) {
+ out << path.path;
+ return out;
+}
+
+lsDocumentUri lsDocumentUri::FromPath(const AbsolutePath& path) {
+ lsDocumentUri result;
+ result.SetPath(path);
+ return result;
+}
+//void lsDocumentUri::SetPath(const AbsolutePath& path)
+//{
+// raw_uri_ = make_file_scheme_uri(path.path);
+//}
+//
+void lsDocumentUri::SetPath(const AbsolutePath& path) {
+ // file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
+ raw_uri_ = path;
+
+ size_t index = raw_uri_.find(":");
+ if (index == 1) { // widows drive letters must always be 1 char
+ raw_uri_.replace(raw_uri_.begin() + index, raw_uri_.begin() + index + 1,
+ "%3A");
+ }
+
+ // subset of reserved characters from the URI standard
+ // http://www.ecma-international.org/ecma-262/6.0/#sec-uri-syntax-and-semantics
+ std::string t;
+ t.reserve(8 + raw_uri_.size());
+
+ // TODO: proper fix
+#if defined(_WIN32)
+ t += "file:///";
+#else
+ t += "file://";
+#endif
+
+ // clang-format off
+ for (char c : raw_uri_)
+ switch (c) {
+ case ' ': t += "%20"; break;
+ case '#': t += "%23"; break;
+ case '$': t += "%24"; break;
+ case '&': t += "%26"; break;
+ case '(': t += "%28"; break;
+ case ')': t += "%29"; break;
+ case '+': t += "%2B"; break;
+ case ',': t += "%2C"; break;
+ case ';': t += "%3B"; break;
+ case '?': t += "%3F"; break;
+ case '@': t += "%40"; break;
+ default: t += c; break;
+ }
+ // clang-format on
+ raw_uri_ = std::move(t);
+}
+
+std::string lsDocumentUri::GetRawPath() const {
+
+
+ if (raw_uri_.compare(0, 8, "file:///"))
+ return raw_uri_;
+
+
+ std::string ret;
+#if defined(_WIN32)
+ size_t i = 8;
+#else
+ size_t i = 7;
+#endif
+ auto from_hex = [](unsigned char c) {
+ return c - '0' < 10 ? c - '0' : (c | 32) - 'a' + 10;
+ };
+ for (; i < raw_uri_.size(); i++) {
+ if (i + 3 <= raw_uri_.size() && raw_uri_[i] == '%') {
+ ret.push_back(from_hex(raw_uri_[i + 1]) * 16 + from_hex(raw_uri_[i + 2]));
+ i += 2;
+ }
+ else
+ ret.push_back(raw_uri_[i] == '\\' ? '/' : raw_uri_[i]);
+ }
+ return ret;
+}
+
+lsDocumentUri::lsDocumentUri() {}
+
+
+lsDocumentUri::lsDocumentUri(const AbsolutePath& path)
+{
+ SetPath(path);
+}
+
+lsDocumentUri::lsDocumentUri(const lsDocumentUri& other): raw_uri_(other.raw_uri_)
+{
+}
+
+bool lsDocumentUri::operator==(const lsDocumentUri& other) const {
+ return raw_uri_ == other.raw_uri_;
+}
+
+bool lsDocumentUri::operator==(const std::string& other) const
+{
+ return raw_uri_ == other;
+}
+
+
+AbsolutePath lsDocumentUri::GetAbsolutePath() const {
+
+
+ if (raw_uri_.find("file://") != std::string::npos){
+ try
+ {
+ return lsp::NormalizePath(GetRawPath(), false /*ensure_exists*/, false);
+ }
+ catch (std::exception&)
+ {
+ return AbsolutePath("", false);
+ }
+ }
+
+ return AbsolutePath(raw_uri_,false);
+
+}
+
+AbsolutePath::AbsolutePath(const std::string& path, bool validate)
+ : path(path) {
+ // TODO: enable validation after fixing tests.
+ if (validate && !lsp::IsAbsolutePath(path)) {
+ qualify = false;
+ auto temp = lsp::NormalizePath(path,false);
+ if(!temp.path.empty())
+ {
+ this->path = temp.path;
+ }
+ }
+}
+
+void Reflect(Writer& visitor, lsDocumentUri& value) {
+ Reflect(visitor, value.raw_uri_);
+}
+void Reflect(Reader& visitor, lsDocumentUri& value) {
+ Reflect(visitor, value.raw_uri_);
+ // Only record the path when we deserialize a URI, since it most likely came
+ // from the client.
+
+}
+
+ std::string ProgressReport::ToString() const
+{
+ std::string info;
+ info += "id:" + id + "\n";
+ info += "task:" + task + "\n";
+ info += "subTask:" + subTask + "\n";
+ info += "status:" + status + "\n";
+ {
+ std::stringstream ss;
+ ss << "totalWork:" << totalWork << std::endl;
+ info += ss.str();
+ }
+ {
+ std::stringstream ss;
+ ss << "workDone:" << workDone << std::endl;
+ info += ss.str();
+ }
+
+ {
+ std::stringstream ss;
+ ss << "complete:" << complete << std::endl;
+ info += ss.str();
+ }
+
+ return info;
+}
+
+std::string EventNotification::ToString() const
+{
+ std::string info;
+ if (ClasspathUpdated == eventType)
+ {
+ info += "eventType:ClasspathUpdated\n";
+ }
+ else if (ProjectsImported == eventType)
+ {
+ info += "eventType:ProjectsImported\n";
+ }
+ else
+ {
+ std::ostringstream oss;
+ oss << std::hex << eventType << std::endl;
+
+ info += "eventType:";
+ info += oss.str();
+ }
+ info += "data:" + data.Data() + "\n";
+ return info;
+}
+
+std::string lsp::ToString(lsCompletionItemKind _kind)
+{
+ switch (_kind) {
+ case lsCompletionItemKind::Text:
+ return "Text";
+ case lsCompletionItemKind::Method:
+ return "Method";
+ case lsCompletionItemKind::Function:
+ return "";
+ case lsCompletionItemKind::Constructor:
+ return "Function";
+ case lsCompletionItemKind::Field:
+ return "Field";
+ case lsCompletionItemKind::Variable:
+ return "";
+ case lsCompletionItemKind::Class:
+ return "Variable";
+ case lsCompletionItemKind::Interface:
+ return "Interface";
+ case lsCompletionItemKind::Module:
+ return "Module";
+ case lsCompletionItemKind::Property:
+ return "Property";
+ case lsCompletionItemKind::Unit:
+ return "Unit";
+ case lsCompletionItemKind::Value:
+ return "Value";
+ case lsCompletionItemKind::Enum:
+ return "Enum";
+ case lsCompletionItemKind::Keyword:
+ return "Keyword";
+ case lsCompletionItemKind::Snippet:
+ return "Snippet";
+ case lsCompletionItemKind::Color:
+ return "Color";
+ case lsCompletionItemKind::File:
+ return "File";
+ case lsCompletionItemKind::Reference:
+ return "Reference";
+ case lsCompletionItemKind::Folder:
+ return "Folder";
+ case lsCompletionItemKind::EnumMember:
+ return "EnumMember";
+ case lsCompletionItemKind::Constant:
+ return "Constant";
+ case lsCompletionItemKind::Struct:
+ return "Struct";
+ case lsCompletionItemKind::Event:
+ return "Event";
+ case lsCompletionItemKind::Operator:
+ return "Operator";
+ case lsCompletionItemKind::TypeParameter:
+ return "TypeParameter";
+ default:
+ return "Unknown";
+ }
+}
+
+std::string lsp::ToString(lsInsertTextFormat _kind)
+{
+ if (_kind == lsInsertTextFormat::PlainText)
+ {
+ return "PlainText";
+ }
+ else if (_kind == lsInsertTextFormat::Snippet)
+ {
+ return "Snippet";
+ }else
+ {
+ return "Unknown";
+ }
+}
+
+const std::string& lsCompletionItem::InsertedContent() const
+{
+ if (textEdit)
+ return textEdit->newText;
+ if (insertText.has_value() && !insertText->empty())
+ return insertText.value();
+ return label;
+}
+
+std::string lsCompletionItem::DisplayText()
+{
+
+ if (detail)
+ {
+
+ return label + " in " + detail.value();
+ }
+ return label;
+}
+
+std::string lsCompletionItem::ToString()
+ {
+ std::stringstream info;
+ info << "label : " << label << std::endl;
+ if(kind)
+ info << "kind : " << lsp::ToString(kind.value()) << std::endl;
+ else
+ info << "kind : no exist." << std::endl;
+
+ if (detail)
+ info << "detail : " << detail.value() << std::endl;
+ else
+ info << "detail : no exist." << std::endl;
+
+ if (documentation)
+ {
+ info << "documentation : " << std::endl;
+ if(documentation.value().first)
+ {
+ info << documentation.value().first.value();
+ }
+ else if(documentation.value().second)
+ {
+ info << documentation.value().second.value().value;
+ }
+ }
+ else
+ info << "documentation : no exist." << std::endl;
+
+ if (deprecated)
+ info << "deprecated : " << deprecated.value() << std::endl;
+ else
+ info << "deprecated : no exist." << std::endl;
+
+ if (preselect)
+ info << "preselect : " << preselect.value() << std::endl;
+ else
+ info << "preselect : no exist." << std::endl;
+
+ if (sortText)
+ info << "sortText : " << sortText.value() << std::endl;
+ else
+ info << "sortText : no exist." << std::endl;
+
+ if (filterText)
+ info << "filterText : " << filterText.value() << std::endl;
+ else
+ info << "filterText : no exist." << std::endl;
+
+
+ if (insertText)
+ info << "insertText : " << insertText.value() << std::endl;
+ else
+ info << "insertText : no exist." << std::endl;
+
+
+ if (insertTextFormat)
+ info << "insertText : " << lsp::ToString(insertTextFormat.value()) << std::endl;
+ else
+ info << "insertTextFormat : no exist." << std::endl;
+
+ if (textEdit)
+ info << "textEdit : " << textEdit.value().ToString() << std::endl;
+ else
+ info << "textEdit : no exist." << std::endl;
+
+
+
+ return info.str();
+
+ }
+namespace JDT
+{
+ namespace CodeActionKind {
+
+
+ /**
+ * Base kind for quickfix actions: 'quickfix'
+ */
+ const char* QuickFix = "quickfix";
+
+ /**
+ * Base kind for refactoring actions: 'refactor'
+ */
+ const char* Refactor = "refactor";
+
+ /**
+ * Base kind for refactoring extraction actions: 'refactor.extract'
+ *
+ * Example extract actions:
+ *
+ * - Extract method - Extract function - Extract variable - Extract interface
+ * from class - ...
+ */
+ const char* RefactorExtract = "refactor.extract";
+
+ /**
+ * Base kind for refactoring inline actions: 'refactor.inline'
+ *
+ * Example inline actions:
+ *
+ * - Inline function - Inline variable - Inline constant - ...
+ */
+ const char* RefactorInline = "refactor.inline";
+
+ /**
+ * Base kind for refactoring rewrite actions: 'refactor.rewrite'
+ *
+ * Example rewrite actions:
+ *
+ * - Convert JavaScript function to class - Add or remove parameter -
+ * Encapsulate field - Make method static - Move method to base class - ...
+ */
+ const char* RefactorRewrite = "refactor.rewrite";
+
+ /**
+ * Base kind for source actions: `source`
+ *
+ * Source code actions apply to the entire file.
+ */
+ const char* Source = "source";
+
+ /**
+ * Base kind for an organize imports source action: `source.organizeImports`
+ */
+ const char* SourceOrganizeImports = "source.organizeImports";
+
+ const char* COMMAND_ID_APPLY_EDIT = "java.apply.workspaceEdit";
+
+ };
+
+
+}
+Directory::Directory(const AbsolutePath& path) : path(path.path) {
+ lsp::EnsureEndsInSlash(this->path);
+}
+
+bool Directory::operator==(const Directory& rhs) const {
+ return path == rhs.path;
+}
+
+bool Directory::operator!=(const Directory& rhs) const {
+ return path != rhs.path;
+}
+
+
+
+ Registration Registration::Create(const std::string& method)
+{
+ Registration reg;
+ reg.method = method;
+ const boost::uuids::uuid a_uuid = boost::uuids::random_generator()();
+ reg.id = to_string(a_uuid);
+ return reg;
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_code_action.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_code_action.h
new file mode 100644
index 0000000000..37acc6ca61
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_code_action.h
@@ -0,0 +1,64 @@
+#pragma once
+
+
+#include "location_type.h"
+#include "lsDocumentUri.h"
+#include "lsTextEdit.h"
+#include "lsPosition.h"
+
+// codeAction
+struct CommandArgs {
+ lsDocumentUri textDocumentUri;
+ std::vector<lsTextEdit> edits;
+};
+MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(CommandArgs, textDocumentUri, edits);
+inline void Reflect(Reader& visitor, CommandArgs& value) {
+ int i = 0;
+ visitor.IterArray([&](Reader& visitor) {
+ switch (i++) {
+ case 0:
+ Reflect(visitor, value.textDocumentUri);
+ break;
+ case 1:
+ Reflect(visitor, value.edits);
+ break;
+
+ }
+ });
+}
+
+// codeLens
+struct lsCodeLensUserData {};
+MAKE_REFLECT_EMPTY_STRUCT(lsCodeLensUserData);
+
+struct lsCodeLensCommandArguments {
+ lsDocumentUri uri;
+ lsPosition position;
+ std::vector<lsLocation> locations;
+};
+
+// FIXME Don't use array in vscode-cquery
+inline void Reflect(Writer& visitor, lsCodeLensCommandArguments& value) {
+ visitor.StartArray(3);
+ Reflect(visitor, value.uri);
+ Reflect(visitor, value.position);
+ Reflect(visitor, value.locations);
+ visitor.EndArray();
+}
+
+inline void Reflect(Reader& visitor, lsCodeLensCommandArguments& value) {
+ int i = 0;
+ visitor.IterArray([&](Reader& visitor) {
+ switch (i++) {
+ case 0:
+ Reflect(visitor, value.uri);
+ break;
+ case 1:
+ Reflect(visitor, value.position);
+ break;
+ case 2:
+ Reflect(visitor, value.locations);
+ break;
+ }
+ });
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_completion.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_completion.h
new file mode 100644
index 0000000000..250699a44a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_completion.h
@@ -0,0 +1,224 @@
+#pragma once
+#include "lsTextEdit.h"
+#include "lsMarkedString.h"
+#include "lsCommand.h"
+
+
+// The kind of a completion entry.
+enum class lsCompletionItemKind {
+ Text = 1,
+ Method = 2,
+ Function = 3,
+ Constructor = 4,
+ Field = 5,
+ Variable = 6,
+ Class = 7,
+ Interface = 8,
+ Module = 9,
+ Property = 10,
+ Unit = 11,
+ Value = 12,
+ Enum = 13,
+ Keyword = 14,
+ Snippet = 15,
+ Color = 16,
+ File = 17,
+ Reference = 18,
+ Folder = 19,
+ EnumMember = 20,
+ Constant = 21,
+ Struct = 22,
+ Event = 23,
+ Operator = 24,
+ TypeParameter = 25,
+};
+MAKE_REFLECT_TYPE_PROXY(lsCompletionItemKind);
+
+
+
+// Defines whether the insert text in a completion item should be interpreted as
+// plain text or a snippet.
+enum class lsInsertTextFormat {
+ // The primary text to be inserted is treated as a plain string.
+ PlainText = 1,
+
+ // The primary text to be inserted is treated as a snippet.
+ //
+ // A snippet can define tab stops and placeholders with `$1`, `$2`
+ // and `${3:foo}`. `$0` defines the final tab stop, it defaults to
+ // the end of the snippet. Placeholders with equal identifiers are linked,
+ // that is typing in one will update others too.
+ //
+ // See also:
+ // https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
+ Snippet = 2
+};
+MAKE_REFLECT_TYPE_PROXY(lsInsertTextFormat);
+
+namespace lsp
+{
+ std::string ToString(lsCompletionItemKind);
+ std::string ToString(lsInsertTextFormat);
+}
+/**
+ * The Completion request is sent from the client to the server to compute completion items at a given cursor position.
+ * Completion items are presented in the IntelliSense user class. If computing complete completion items is expensive
+ * servers can additional provide a handler for the resolve completion item request. This request is send when a
+ * completion item is selected in the user class.
+ */
+struct lsCompletionItem {
+
+ // The label of this completion item. By default
+ // also the text that is inserted when selecting
+ // this completion.
+ std::string label;
+
+ // The kind of this completion item. Based of the kind
+ // an icon is chosen by the editor.
+ boost::optional<lsCompletionItemKind> kind ;
+
+ // A human-readable string with additional information
+ // about this item, like type or symbol information.
+ boost::optional < std::string > detail;
+
+ // A human-readable string that represents a doc-comment.
+ boost::optional< std::pair<boost::optional< std::string> , boost::optional<MarkupContent> > > documentation;
+
+
+ /**
+ * Indicates if this item is deprecated.
+ */
+ boost::optional< bool >deprecated;
+
+
+ /**
+ * Select this item when showing.
+ *
+ * *Note* that only one completion item can be selected and that the
+ * tool / client decides which item that is. The rule is that the *first
+ * item of those that match best is selected.
+ */
+ boost::optional< bool > preselect;
+
+
+ // Internal information to order candidates.
+ int relevance = 0;
+
+ // A string that shoud be used when comparing this item
+ // with other items. When `falsy` the label is used.
+ boost::optional< std::string > sortText;
+
+ // A string that should be used when filtering a set of
+ // completion items. When `falsy` the label is used.
+ boost::optional<std::string> filterText;
+
+ // A string that should be inserted a document when selecting
+ // this completion. When `falsy` the label is used.
+ boost::optional<std::string> insertText;
+
+ // The format of the insert text. The format applies to both the `insertText`
+ // property and the `newText` property of a provided `textEdit`.
+ boost::optional< lsInsertTextFormat> insertTextFormat ;
+
+ // An edit which is applied to a document when selecting this completion. When
+ // an edit is provided the value of `insertText` is ignored.
+ //
+ // *Note:* The range of the edit must be a single line range and it must
+ // contain the position at which completion has been requested.
+ boost::optional<lsTextEdit> textEdit;
+
+ // An boost::optional array of additional text edits that are applied when
+ // selecting this completion. Edits must not overlap with the main edit
+ // nor with themselves.
+ // std::vector<TextEdit> additionalTextEdits;
+
+ // An boost::optional command that is executed *after* inserting this completion.
+ // *Note* that additional modifications to the current document should be
+ // described with the additionalTextEdits-property. Command command;
+
+ // An data entry field that is preserved on a completion item between
+ // a completion and a completion resolve request.
+ // data ? : any
+
+ // Use this helper to figure out what content the completion item will insert
+ // into the document, as it could live in either |textEdit|, |insertText|, or
+ // |label|.
+ const std::string& InsertedContent() const;
+
+ std::string DisplayText();
+ /**
+ * An boost::optional array of additional text edits that are applied when
+ * selecting this completion. Edits must not overlap (including the same insert position)
+ * with the main edit nor with themselves.
+ *
+ * Additional text edits should be used to change text unrelated to the current cursor position
+ * (for example adding an import statement at the top of the file if the completion item will
+ * insert an unqualified type).
+ */
+ boost::optional<std::vector<lsTextEdit> >additionalTextEdits;
+
+ /**
+* An boost::optional set of characters that when pressed while this completion is active will accept it first and
+* then type that character. *Note* that all commit characters should have `length=1` and that superfluous
+* characters will be ignored.
+*/
+ boost::optional< std::vector<std::string> > commitCharacters;
+
+ /**
+* An boost::optional command that is executed *after* inserting this completion. *Note* that
+* additional modifications to the current document should be described with the
+* additionalTextEdits-property.
+*/
+ boost::optional<lsCommandWithAny> command;
+
+ /**
+* An data entry field that is preserved on a completion item between a completion and a completion resolve request.
+*/
+ boost::optional<lsp::Any> data;
+ std::string ToString();
+ MAKE_SWAP_METHOD(lsCompletionItem,
+ label,
+ kind,
+ detail,
+ documentation,
+ sortText,
+ insertText,
+ filterText,
+ insertTextFormat,
+ textEdit,
+ deprecated, preselect, additionalTextEdits, commitCharacters,
+ command, data);
+
+};
+
+
+
+MAKE_REFLECT_STRUCT(lsCompletionItem,
+ label,
+ kind,
+ detail,
+ documentation,
+ sortText,
+ insertText,
+ filterText,
+ insertTextFormat,
+ textEdit,
+ deprecated, preselect, additionalTextEdits, commitCharacters,
+ command, data);
+
+
+
+struct CompletionList {
+ // This list it not complete. Further typing should result in recomputing
+ // this list.
+ bool isIncomplete = false;
+ // The completion items.
+ std::vector<lsCompletionItem> items;
+
+ void swap(CompletionList& arg) noexcept
+ {
+ items.swap(arg.items);
+ std::swap(isIncomplete, arg.isIncomplete);
+ }
+};
+MAKE_REFLECT_STRUCT(CompletionList, isIncomplete, items); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.cpp
new file mode 100644
index 0000000000..c323706dc0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.cpp
@@ -0,0 +1,74 @@
+#include "lsp_diagnostic.h"
+bool lsDiagnostic::operator==(const lsDiagnostic& rhs) const {
+ // Just check the important fields.
+ return range == rhs.range && message == rhs.message;
+}
+bool lsDiagnostic::operator!=(const lsDiagnostic& rhs) const {
+ return !(*this == rhs);
+}
+
+std::string lsResponseError::ToString()
+{
+ std::string info = "code:";
+ switch (code)
+ {
+ case lsErrorCodes::ParseError:
+ info += "ParseError\n";
+ break;
+ case lsErrorCodes::InvalidRequest:
+ info += "InvalidRequest\n";
+ break;
+ case lsErrorCodes::MethodNotFound:
+ info += "MethodNotFound\n";
+ break;
+ case lsErrorCodes::InvalidParams:
+ info += "InvalidParams\n";
+ break;
+ case lsErrorCodes::InternalError:
+ info += "InternalError\n";
+ break;
+ case lsErrorCodes::serverErrorStart:
+ info += "serverErrorStart\n";
+ break;
+ case lsErrorCodes::serverErrorEnd:
+ info += "serverErrorEnd\n";
+ break;
+ case lsErrorCodes::ServerNotInitialized:
+ info += "ServerNotInitialized\n";
+ break;
+ case lsErrorCodes::UnknownErrorCode:
+ info += "UnknownErrorCode\n";
+ break;
+ // Defined by the protocol.
+ case lsErrorCodes::RequestCancelled:
+ info += "RequestCancelled\n";
+ break;
+ default:
+ {
+ std::stringstream ss;
+ ss << "unknown code:" << (int32_t)code << std::endl;
+ info += ss.str();
+ }
+ break;
+ }
+ info += "message:" + message;
+ info += "\n";
+
+ if(data.has_value())
+ {
+
+ info += "data:" + data.value().Data();
+ info += "\n";
+ }
+ return info;
+}
+
+void lsResponseError::Write(Writer& visitor) {
+ auto& value = *this;
+ int code2 = static_cast<int>(this->code);
+
+ visitor.StartObject();
+ REFLECT_MEMBER2("code", code2);
+ REFLECT_MEMBER(message);
+ visitor.EndObject();
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.h b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.h
new file mode 100644
index 0000000000..d1b1d1ba78
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/lsp_diagnostic.h
@@ -0,0 +1,151 @@
+#pragma once
+#include "lsRange.h"
+#include "lsTextEdit.h"
+#include "lsDocumentUri.h"
+
+#include "lsResponseError.h"
+#include "location_type.h"
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+enum class lsDiagnosticSeverity {
+ // Reports an error.
+ Error = 1,
+ // Reports a warning.
+ Warning = 2,
+ // Reports an information.
+ Information = 3,
+ // Reports a hint.
+ Hint = 4
+};
+MAKE_REFLECT_TYPE_PROXY(lsDiagnosticSeverity);
+
+/**
+ * The diagnostic tags.
+ *
+ * @since 3.15.0
+ */
+enum class DiagnosticTag :uint8_t {
+
+ /**
+ * Unused or unnecessary code.
+ *
+ * Clients are allowed to render diagnostics with this tag faded out instead of having
+ * an error squiggle.
+ */
+ Unnecessary=(1),
+
+ /**
+ * Deprecated or obsolete code.
+ *
+ * Clients are allowed to rendered diagnostics with this tag strike through.
+ */
+ Deprecated=(2),
+};
+MAKE_REFLECT_TYPE_PROXY(DiagnosticTag);
+
+
+
+/**
+ * Represents a related message and source code location for a diagnostic. This should be
+ * used to point to code locations that cause or related to a diagnostics, e.g when duplicating
+ * a symbol in a scope.
+ *
+ * Since 3.7.0
+ */
+
+struct DiagnosticRelatedInformation {
+ /**
+ * The location of this related diagnostic information.
+ */
+
+ lsLocation location;
+
+ /**
+ * The message of this related diagnostic information.
+ */
+
+ std::string message;
+
+ MAKE_SWAP_METHOD(DiagnosticRelatedInformation, location, message)
+};
+MAKE_REFLECT_STRUCT(DiagnosticRelatedInformation, location, message)
+/**
+ * Structure to capture a description for an error code.
+ *
+ * @since 3.16.0
+ */
+struct DiagnosticCodeDescription {
+ /**
+ * An URI to open with more information about the diagnostic error.
+ */
+ std::string href;
+ MAKE_SWAP_METHOD(DiagnosticCodeDescription, href)
+};
+MAKE_REFLECT_STRUCT(DiagnosticCodeDescription, href)
+
+//Represents a diagnostic, such as a compiler error or warning.Diagnostic objects are only valid in the scope of a resource.
+struct lsDiagnostic {
+ // The range at which the message applies.
+ lsRange range;
+
+ // The diagnostic's severity. Can be omitted. If omitted it is up to the
+ // client to interpret diagnostics as error, warning, info or hint.
+ boost::optional<lsDiagnosticSeverity> severity;
+
+ // The diagnostic's code. Can be omitted.
+ boost::optional< std::pair<boost::optional<std::string>, boost::optional<int>> > code;
+
+ boost::optional<DiagnosticCodeDescription> codeDescription;
+ // A human-readable string describing the source of this
+ // diagnostic, e.g. 'typescript' or 'super lint'.
+ boost::optional < std::string >source ;
+
+ // The diagnostic's message.
+ std::string message;
+
+ // Non-serialized set of fixits.
+ std::vector<lsTextEdit> fixits_;
+
+ /**
+ * Additional metadata about the diagnostic.
+ *
+ * @since 3.15.0
+ */
+ boost::optional<std::vector<DiagnosticTag>> tags;
+
+
+ /**
+ * An array of related diagnostic information, e.g. when symbol-names within a scope collide
+ * all definitions can be marked via this property.
+ *
+ * Since 3.7.0
+ */
+ boost::optional<std::vector<DiagnosticRelatedInformation>> relatedInformation;
+
+ /**
+ * A data entry field that is preserved between a
+ * `textDocument/publishDiagnostics` notification and
+ * `textDocument/codeAction` request.
+ *
+ * @since 3.16.0
+ */
+ boost::optional<lsp::Any> data;
+ bool operator==(const lsDiagnostic& rhs) const;
+ bool operator!=(const lsDiagnostic& rhs) const;
+
+ MAKE_SWAP_METHOD(lsDiagnostic, range, severity, code, codeDescription, source, message, tags, data)
+};
+MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, code, codeDescription, source, message, tags, data)
+
+
+
+struct Rsp_Error : ResponseError<lsResponseError, Rsp_Error> {
+
+ MAKE_SWAP_METHOD(Rsp_Error, jsonrpc, id, error)
+};
+MAKE_REFLECT_STRUCT(Rsp_Error, jsonrpc, id, error)
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/method_type.h b/graphics/asymptote/LspCpp/LibLsp/lsp/method_type.h
new file mode 100644
index 0000000000..dcbb4a851a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/method_type.h
@@ -0,0 +1,7 @@
+#pragma once
+#include <string>
+
+using MethodType = const char* const;
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/out_list.h b/graphics/asymptote/LspCpp/LibLsp/lsp/out_list.h
new file mode 100644
index 0000000000..36c4aa78ba
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/out_list.h
@@ -0,0 +1,22 @@
+#pragma once
+
+
+#include "location_type.h"
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+
+
+//DEFINE_RESPONCE_TYPE(Rsp_FindLinkLocationList, std::vector<LinkLocation>);
+//DEFINE_RESPONCE_TYPE(Rsp_LocationList, std::vector<lsLocation>);
+
+
+namespace LocationListEither{
+
+ typedef std::pair< boost::optional<std::vector<lsLocation>> , boost::optional<std::vector<LocationLink> > > Either;
+
+};
+extern void Reflect(Reader& visitor, LocationListEither::Either& value);
+//DEFINE_RESPONCE_TYPE(Rsp_LocationListEither, LocationListEither::Either);
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/symbol.h b/graphics/asymptote/LspCpp/LibLsp/lsp/symbol.h
new file mode 100644
index 0000000000..57298b8d7f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/symbol.h
@@ -0,0 +1,164 @@
+#pragma once
+#include "LibLsp/lsp/location_type.h"
+
+
+enum class lsSymbolKind : uint8_t {
+ Unknown = 0,
+
+ File = 1,
+ Module = 2,
+ Namespace = 3,
+ Package = 4,
+ Class = 5,
+ Method = 6,
+ Property = 7,
+ Field = 8,
+ Constructor = 9,
+ Enum = 10,
+ Interface = 11,
+ Function = 12,
+ Variable = 13,
+ Constant = 14,
+ String = 15,
+ Number = 16,
+ Boolean = 17,
+ Array = 18,
+ Object = 19,
+ Key = 20,
+ Null = 21,
+ EnumMember = 22,
+ Struct = 23,
+ Event = 24,
+ Operator = 25,
+
+ // For C++, this is interpreted as "template parameter" (including
+ // non-type template parameters).
+ TypeParameter = 26,
+
+ // cquery extensions
+ // See also https://github.com/Microsoft/language-server-protocol/issues/344
+ // for new SymbolKind clang/Index/IndexSymbol.h clang::index::SymbolKind
+ TypeAlias = 252,
+ Parameter = 253,
+ StaticMethod = 254,
+ Macro = 255,
+};
+MAKE_REFLECT_TYPE_PROXY(lsSymbolKind);
+
+typedef lsSymbolKind SymbolKind;
+
+// A document highlight kind.
+enum class lsDocumentHighlightKind {
+ // A textual occurrence.
+ Text = 1,
+ // Read-access of a symbol, like reading a variable.
+ Read = 2,
+ // Write-access of a symbol, like writing to a variable.
+ Write = 3
+};
+MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind);
+
+// A document highlight is a range inside a text document which deserves
+// special attention. Usually a document highlight is visualized by changing
+// the background color of its range.
+struct lsDocumentHighlight {
+ // The range this highlight applies to.
+ lsRange range;
+
+ // The highlight kind, default is DocumentHighlightKind.Text.
+ boost::optional<lsDocumentHighlightKind> kind ;
+
+ MAKE_SWAP_METHOD(lsDocumentHighlight, range, kind)
+};
+MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind);
+
+struct lsSymbolInformation {
+
+/**
+ * The name of this symbol.
+ */
+ std::string name;
+ /**
+ * The kind of this symbol.
+ */
+ lsSymbolKind kind;
+ /**
+* Indicates if this symbol is deprecated.
+*/
+ boost::optional<bool> deprecated;
+ /**
+ * The location of this symbol. The location's range is used by a tool
+ * to reveal the location in the editor. If the symbol is selected in the
+ * tool the range's start information is used to position the cursor. So
+ * the range usually spans more then the actual symbol's name and does
+ * normally include things like visibility modifiers.
+ *
+ * The range doesn't have to denote a node range in the sense of a abstract
+ * syntax tree. It can therefore not be used to re-construct a hierarchy of
+ * the symbols.
+ */
+ lsLocation location;
+ /**
+ * The name of the symbol containing this symbol. This information is for
+ * user interface purposes (e.g. to render a qualifier in the user interface
+ * if necessary). It can't be used to re-infer a hierarchy for the document
+ * symbols.
+ */
+ boost::optional<std::string> containerName;
+
+
+ MAKE_SWAP_METHOD(lsSymbolInformation, name, kind, deprecated, location, containerName);
+};
+MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, deprecated, location, containerName);
+
+
+struct lsDocumentSymbol {
+ /**
+ * The name of this symbol.
+ */
+
+ std::string name;
+
+ /**
+ * The kind of this symbol.
+ */
+
+ lsSymbolKind kind = lsSymbolKind::Unknown;
+
+ /**
+ * The range enclosing this symbol not including leading/trailing whitespace but everything else
+ * like comments. This information is typically used to determine if the clients cursor is
+ * inside the symbol to reveal in the symbol in the UI.
+ */
+
+ lsRange range;
+
+ /**
+ * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
+ * Must be contained by the `range`.
+ */
+
+ lsRange selectionRange;
+
+ /**
+ * More detail for this symbol, e.g the signature of a function. If not provided the
+ * name is used.
+ */
+ boost::optional< std::string > detail;
+
+ /**
+ * Indicates if this symbol is deprecated.
+ */
+ boost::optional< bool > deprecated;
+
+ /**
+ * Children of this symbol, e.g. properties of a class.
+ */
+ boost::optional < std::vector<lsDocumentSymbol> > children;
+
+ //internal use
+ int flags=0;
+
+ MAKE_SWAP_METHOD(lsDocumentSymbol, name, kind, range, selectionRange, detail, deprecated, children, flags);
+};
+MAKE_REFLECT_STRUCT(lsDocumentSymbol, name, kind, range, selectionRange, detail, deprecated, children, flags); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h
new file mode 100644
index 0000000000..612d186f6f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h
@@ -0,0 +1,267 @@
+#pragma once
+
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+enum class HighlightingKind_clangD {
+ Variable = 0,
+ LocalVariable,
+ Parameter,
+ Function,
+ Method,
+ StaticMethod,
+ Field,
+ StaticField,
+ Class,
+ Interface,
+ Enum,
+ EnumConstant,
+ Typedef,
+ Type,
+ Unknown,
+ Namespace,
+ TemplateParameter,
+ Concept,
+ Primitive,
+ Macro,
+
+ // This one is different from the other kinds as it's a line style
+ // rather than a token style.
+ InactiveCode,
+
+ LastKind = InactiveCode
+};
+std::string toSemanticTokenType(HighlightingKind_clangD kind);
+
+enum class HighlightingModifier_clangD {
+ Declaration,
+ Deprecated,
+ Deduced,
+ Readonly,
+ Static,
+ Abstract,
+ DependentName,
+ DefaultLibrary,
+
+ FunctionScope,
+ ClassScope,
+ FileScope,
+ GlobalScope,
+
+ LastModifier = GlobalScope
+};
+std::string toSemanticTokenModifier(HighlightingModifier_clangD modifier);
+
+enum SemanticTokenType {
+ ls_namespace=0,// 'namespace',
+ /**
+ * Represents a generic type. Acts as a fallback for types which
+ * can't be mapped to a specific type like class or enum.
+ */
+ ls_type,// 'type',
+ ls_class,// 'class',
+ ls_enum,// 'enum',
+ ls_interface,// 'interface',
+ ls_struct,// 'struct',
+ ls_typeParameter,// 'typeParameter',
+ ls_parameter,// 'parameter',
+ ls_variable,// 'variable',
+ ls_property,// 'property',
+ ls_enumMember,// 'enumMember',
+ ls_event,// 'event',
+ ls_function,// 'function',
+ ls_method,// 'method',
+ ls_macro,// 'macro',
+ ls_keyword,// 'keyword',
+ ls_modifier,// 'modifier',
+ ls_comment,// 'comment',
+ ls_string,// 'string',
+ ls_number,// 'number',
+ ls_regexp,// 'regexp',
+ ls_operator,// 'operator'
+ lastKind = ls_operator
+};
+std::string to_string(SemanticTokenType);
+unsigned toSemanticTokenType(std::vector<SemanticTokenType>& modifiers);
+
+enum TokenType_JDT {
+ PACKAGE_JDT=0,
+ CLASS_JDT,
+ INTERFACE_JDT,
+ ENUM_JDT,
+ ENUM_MEMBER_JDT,
+ TYPE_JDT,
+ TYPE_PARAMETER_JDT,
+ ANNOTATION_JDT,
+ ANNOTATION_MEMBER_JDT,
+ METHOD_JDT,
+ PROPERTY_JDT,
+ VARIABLE_JDT,
+ PARAMETER_JDT
+};
+std::string to_string(TokenType_JDT);
+
+enum SemanticTokenModifier {
+ ls_declaration=0,// 'declaration',
+ ls_definition,// 'definition',
+ ls_readonly,// 'readonly',
+ ls_static,// 'static',
+ ls_deprecated,// 'deprecated',
+ ls_abstract,// 'abstract',
+ ls_async,// 'async',
+ ls_modification,// 'modification',
+ ls_documentation,// 'documentation',
+ ls_defaultLibrary,// 'defaultLibrary'
+ LastModifier = ls_defaultLibrary
+};
+std::string to_string(SemanticTokenModifier);
+unsigned toSemanticTokenModifiers(std::vector<SemanticTokenModifier>&);
+/// Specifies a single semantic token in the document.
+/// This struct is not part of LSP, which just encodes lists of tokens as
+/// arrays of numbers directly.
+struct SemanticToken {
+ /// token line number, relative to the previous token
+ unsigned deltaLine = 0;
+ /// token start character, relative to the previous token
+ /// (relative to 0 or the previous token's start if they are on the same line)
+ unsigned deltaStart = 0;
+ /// the length of the token. A token cannot be multiline
+ unsigned length = 0;
+ /// will be looked up in `SemanticTokensLegend.tokenTypes`
+ unsigned tokenType = 0;
+ /// each set bit will be looked up in `SemanticTokensLegend.tokenModifiers`
+ unsigned tokenModifiers = 0;
+};
+bool operator==(const SemanticToken&, const SemanticToken&);
+struct SemanticTokens{
+
+ /**
+ * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to
+ * the token before it, because most tokens remain stable relative to each other when edits are made in a file.
+ *
+ * ---
+ * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices:
+ * - at index `5*i` - `deltaLine`: token line number, relative to the previous token
+ * - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line)
+ * - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline.
+ * - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536.
+ * - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers`
+ *
+ * ---
+ * ### How to encode tokens
+ *
+ * Here is an example for encoding a file with 3 tokens in a uint32 array:
+ * ```
+ * { line: 2, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] },
+ * { line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] },
+ * { line: 5, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] }
+ * ```
+ *
+ * 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types.
+ * For this example, we will choose the following legend which must be passed in when registering the provider:
+ * ```
+ * tokenTypes: ['property', 'type', 'class'],
+ * tokenModifiers: ['private', 'static']
+ * ```
+ *
+ * 2. The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked
+ * up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags,
+ * so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because
+ * bits 0 and 1 are set. Using this legend, the tokens now are:
+ * ```
+ * { line: 2, startChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 },
+ * { line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 },
+ * { line: 5, startChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 }
+ * ```
+ *
+ * 3. The next step is to represent each token relative to the previous token in the file. In this case, the second token
+ * is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar`
+ * of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the
+ * `startChar` of the third token will not be altered:
+ * ```
+ * { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 },
+ * { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 },
+ * { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 }
+ * ```
+ *
+ * 4. Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation:
+ * ```
+ * // 1st token, 2nd token, 3rd token
+ * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ]
+ * ```
+ */
+ std::vector<int32_t> data;
+ static std::vector<int32_t> encodeTokens(std::vector<SemanticToken>& tokens);
+
+ /**
+ * An optional result id. If provided and clients support delta updating
+ * the client will include the result id in the next semantic token request.
+ * A server can then instead of computing all semantic tokens again simply
+ * send a delta.
+ */
+ boost::optional<std::string> resultId;
+ MAKE_SWAP_METHOD(SemanticTokens, data, resultId)
+};
+MAKE_REFLECT_STRUCT(SemanticTokens, data, resultId)
+
+/// Body of textDocument/semanticTokens/full request.
+struct SemanticTokensParams {
+ /// The text document.
+ lsTextDocumentIdentifier textDocument;
+ MAKE_REFLECT_STRUCT(SemanticTokensParams, textDocument)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensParams, textDocument)
+
+
+/// Body of textDocument/semanticTokens/full/delta request.
+/// Requests the changes in semantic tokens since a previous response.
+struct SemanticTokensDeltaParams {
+ /// The text document.
+ lsTextDocumentIdentifier textDocument;
+ /**
+ * The result id of a previous response. The result Id can either point to
+ * a full response or a delta response depending on what was received last.
+ */
+ std::string previousResultId;
+
+ MAKE_REFLECT_STRUCT(SemanticTokensDeltaParams, textDocument, previousResultId)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensDeltaParams, textDocument, previousResultId)
+
+/// Describes a a replacement of a contiguous range of semanticTokens.
+struct SemanticTokensEdit {
+ // LSP specifies `start` and `deleteCount` which are relative to the array
+ // encoding of the previous tokens.
+ // We use token counts instead, and translate when serializing this struct.
+ unsigned startToken = 0;
+ unsigned deleteTokens = 0;
+ std::vector<int32_t> tokens; // encoded as a flat integer array
+
+ MAKE_REFLECT_STRUCT(SemanticTokensEdit, startToken, deleteTokens, tokens)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensEdit, startToken, deleteTokens, tokens)
+
+
+/// This models LSP SemanticTokensDelta | SemanticTokens, which is the result of
+/// textDocument/semanticTokens/full/delta.
+struct SemanticTokensOrDelta {
+ boost::optional<std::string > resultId;
+ /// Set if we computed edits relative to a previous set of tokens.
+ boost::optional< std::vector<SemanticTokensEdit> > edits;
+ /// Set if we computed a fresh set of tokens.
+ /// Set if we computed edits relative to a previous set of tokens.
+ boost::optional<std::vector<int32_t>> tokens; // encoded as integer array
+ MAKE_REFLECT_STRUCT(SemanticTokensOrDelta, resultId, edits, tokens)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensOrDelta, resultId, edits, tokens)
+
+
+struct SemanticTokensLegend {
+ std::vector<std::string> tokenTypes;
+ std::vector<std::string> tokenModifiers;
+ MAKE_REFLECT_STRUCT(SemanticTokensLegend, tokenTypes, tokenModifiers)
+};
+MAKE_REFLECT_STRUCT(SemanticTokensLegend, tokenTypes, tokenModifiers)
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_semanticTokens_full, SemanticTokensParams,boost::optional<SemanticTokens >,"textDocument/semanticTokens/full")
+DEFINE_REQUEST_RESPONSE_TYPE(td_semanticTokens_full_delta, SemanticTokensDeltaParams, boost::optional<SemanticTokensOrDelta >, "textDocument/semanticTokens/full/delta") \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/callHierarchy.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/callHierarchy.h
new file mode 100644
index 0000000000..a005c182e1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/callHierarchy.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/symbol.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "LibLsp/lsp/lsRange.h"
+
+enum class SymbolTag { Deprecated = 1 };
+MAKE_REFLECT_TYPE_PROXY(SymbolTag)
+
+struct CallHierarchyPrepareParams
+{
+ lsTextDocumentIdentifier textDocument;
+ lsPosition position;
+
+ MAKE_SWAP_METHOD(CallHierarchyPrepareParams,
+ textDocument,
+ position)
+};
+MAKE_REFLECT_STRUCT(CallHierarchyPrepareParams,
+ textDocument,
+ position)
+
+
+
+ /// Represents programming constructs like functions or constructors
+ /// in the context of call hierarchy.
+struct CallHierarchyItem {
+ /// The name of this item.
+ std::string name;
+
+ /// The kind of this item.
+ SymbolKind kind;
+
+ /// Tags for this item.
+ boost::optional<std::vector<SymbolTag>> tags;
+
+ /// More detaill for this item, e.g. the signature of a function.
+ boost::optional<std::string> detail;
+
+ /// The resource identifier of this item.
+ lsDocumentUri uri;
+
+ /**
+ * The range enclosing this symbol not including leading/trailing whitespace
+ * but everything else, e.g. comments and code.
+ */
+ lsRange range;
+
+ /**
+ * The range that should be selected and revealed when this symbol is being
+ * picked, e.g. the name of a function. Must be contained by the
+ * [`range`](#CallHierarchyItem.range).
+ */
+ lsRange selectionRange;
+
+ /**
+ * A data entry field that is preserved between a call hierarchy prepare and
+ * incoming calls or outgoing calls requests.
+ */
+ boost::optional<lsp::Any> data;
+ MAKE_SWAP_METHOD(CallHierarchyItem, name, kind, tags, detail, uri, range, selectionRange, data)
+};
+MAKE_REFLECT_STRUCT(CallHierarchyItem, name, kind, tags, detail, uri, range, selectionRange, data)
+
+
+
+/// The parameter of a `callHierarchy/incomingCalls` request.
+struct CallHierarchyIncomingCallsParams {
+ CallHierarchyItem item;
+ MAKE_SWAP_METHOD(CallHierarchyIncomingCallsParams,item)
+};
+MAKE_REFLECT_STRUCT(CallHierarchyIncomingCallsParams, item)
+
+
+/// Represents an incoming call, e.g. a caller of a method or constructor.
+struct CallHierarchyIncomingCall {
+ /// The item that makes the call.
+ CallHierarchyItem from;
+
+ /// The range at which the calls appear.
+ /// This is relative to the caller denoted by `From`.
+ std::vector<lsRange> fromRanges;
+ MAKE_SWAP_METHOD(CallHierarchyIncomingCall, from, fromRanges)
+};
+MAKE_REFLECT_STRUCT(CallHierarchyIncomingCall, from, fromRanges)
+
+
+
+
+/// The parameter of a `callHierarchy/outgoingCalls` request.
+struct CallHierarchyOutgoingCallsParams {
+ CallHierarchyItem item;
+ MAKE_SWAP_METHOD(CallHierarchyOutgoingCallsParams, item)
+};
+MAKE_REFLECT_STRUCT(CallHierarchyOutgoingCallsParams, item)
+
+/// Represents an outgoing call, e.g. calling a getter from a method or
+/// a method from a constructor etc.
+struct CallHierarchyOutgoingCall {
+ /// The item that is called.
+ CallHierarchyItem to;
+
+ /// The range at which this item is called.
+ /// This is the range relative to the caller, and not `To`.
+ std::vector<lsRange> fromRanges;
+ MAKE_SWAP_METHOD(CallHierarchyOutgoingCall, to, fromRanges)
+};
+MAKE_REFLECT_STRUCT(CallHierarchyOutgoingCall, to, fromRanges)
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_prepareCallHierarchy, CallHierarchyPrepareParams,
+ boost::optional<std::vector<CallHierarchyItem>>, "textDocument/prepareCallHierarchy")
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_incomingCalls, CallHierarchyIncomingCallsParams,
+ boost::optional<std::vector<CallHierarchyIncomingCall>>, "callHierarchy/incomingCalls")
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_outgoingCalls, CallHierarchyOutgoingCallsParams,
+ boost::optional<std::vector<CallHierarchyOutgoingCall>>, "callHierarchy/CallHierarchyOutgoingCall") \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_action.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_action.h
new file mode 100644
index 0000000000..419fdfbc9b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_action.h
@@ -0,0 +1,37 @@
+#pragma once
+#include "LibLsp/lsp/method_type.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+#include "LibLsp/lsp/CodeActionParams.h"
+
+namespace QuickAssistProcessor {
+
+ extern const char* SPLIT_JOIN_VARIABLE_DECLARATION_ID;//$NON-NLS-1$
+ extern const char* CONVERT_FOR_LOOP_ID;// ;// "org.eclipse.jdt.ls.correction.convertForLoop.assist"; //$NON-NLS-1$
+ extern const char* ASSIGN_TO_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.assignToLocal.assist"; //$NON-NLS-1$
+ extern const char* ASSIGN_TO_FIELD_ID ;// "org.eclipse.jdt.ls.correction.assignToField.assist"; //$NON-NLS-1$
+ extern const char* ASSIGN_PARAM_TO_FIELD_ID ;// "org.eclipse.jdt.ls.correction.assignParamToField.assist"; //$NON-NLS-1$
+ extern const char* ASSIGN_ALL_PARAMS_TO_NEW_FIELDS_ID ;// "org.eclipse.jdt.ls.correction.assignAllParamsToNewFields.assist"; //$NON-NLS-1$
+ extern const char* ADD_BLOCK_ID ;// "org.eclipse.jdt.ls.correction.addBlock.assist"; //$NON-NLS-1$
+ extern const char* EXTRACT_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.extractLocal.assist"; //$NON-NLS-1$
+ extern const char* EXTRACT_LOCAL_NOT_REPLACE_ID ;// "org.eclipse.jdt.ls.correction.extractLocalNotReplaceOccurrences.assist"; //$NON-NLS-1$
+ extern const char* EXTRACT_CONSTANT_ID ;// "org.eclipse.jdt.ls.correction.extractConstant.assist"; //$NON-NLS-1$
+ extern const char* INLINE_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.inlineLocal.assist"; //$NON-NLS-1$
+ extern const char* CONVERT_LOCAL_TO_FIELD_ID ;// "org.eclipse.jdt.ls.correction.convertLocalToField.assist"; //$NON-NLS-1$
+ extern const char* CONVERT_ANONYMOUS_TO_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.convertAnonymousToLocal.assist"; //$NON-NLS-1$
+ extern const char* CONVERT_TO_STRING_BUFFER_ID ;// "org.eclipse.jdt.ls.correction.convertToStringBuffer.assist"; //$NON-NLS-1$
+ extern const char* CONVERT_TO_MESSAGE_FORMAT_ID ;// "org.eclipse.jdt.ls.correction.convertToMessageFormat.assist"; //$NON-NLS-1$;
+ extern const char* EXTRACT_METHOD_INPLACE_ID ;// "org.eclipse.jdt.ls.correction.extractMethodInplace.assist"; //$NON-NLS-1$;
+
+ extern const char* CONVERT_ANONYMOUS_CLASS_TO_NESTED_COMMAND ;// "convertAnonymousClassToNestedCommand";
+};
+/**
+ * The code action request is sent from the client to the server to compute
+ * commands for a given text document and range. These commands are
+ * typically code fixes to either fix problems or to beautify/refactor code.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_codeAction, lsCodeActionParams, std::vector<lsCommandWithAny>, "textDocument/codeAction");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_lens.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_lens.h
new file mode 100644
index 0000000000..7fd5ae0cf9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/code_lens.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+struct lsDocumentCodeLensParams {
+
+/**
+ * The document to request code lens for.
+ */
+ lsTextDocumentIdentifier textDocument;
+
+ MAKE_SWAP_METHOD(lsDocumentCodeLensParams, textDocument);
+};
+MAKE_REFLECT_STRUCT(lsDocumentCodeLensParams, textDocument);
+
+
+
+
+struct lsCodeLens {
+ // The range in which this code lens is valid. Should only span a single line.
+ lsRange range;
+ // The command this code lens represents.
+ boost::optional<lsCommandWithAny> command;
+ // A data entry field that is preserved on a code lens item between
+ // a code lens and a code lens resolve request.
+ boost::optional< lsp::Any> data;
+
+ MAKE_SWAP_METHOD(lsCodeLens, range, command, data)
+};
+MAKE_REFLECT_STRUCT(lsCodeLens, range, command, data)
+
+
+
+/**
+ * The code lens request is sent from the client to the server to compute
+ * code lenses for a given text document.
+ *
+ * Registration Options: CodeLensRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_codeLens, lsDocumentCodeLensParams, std::vector<lsCodeLens>, "textDocument/codeLens")
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/colorPresentation.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/colorPresentation.h
new file mode 100644
index 0000000000..22574e3e19
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/colorPresentation.h
@@ -0,0 +1,63 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+#include "LibLsp/lsp/lsRange.h"
+#include "documentColor.h"
+#include "LibLsp/lsp/lsTextEdit.h"
+
+
+struct ColorPresentationParams {
+
+ /**
+ * The text document.
+ */
+ lsTextDocumentIdentifier textDocument;
+
+ /**
+ * The range in the document where this color appers.
+ */
+
+ lsRange range;
+
+ /**
+ * The actual color value for this color range.
+ */
+
+ TextDocument::Color color;
+ MAKE_SWAP_METHOD(ColorPresentationParams, textDocument, range, color)
+};
+MAKE_REFLECT_STRUCT(ColorPresentationParams, textDocument, range, color)
+
+
+struct ColorPresentation {
+ /**
+ * The label of this color presentation. It will be shown on the color
+ * picker header. By default this is also the text that is inserted when selecting
+ * this color presentation.
+ */
+
+ std::string label;
+
+ /**
+ * An edit which is applied to a document when selecting
+ * this presentation for the color. When `null` the label is used.
+ */
+ lsTextEdit textEdit;
+
+ /**
+ * An optional array of additional text edits that are applied when
+ * selecting this color presentation. Edits must not overlap with the main edit nor with themselves.
+ */
+ std::vector<lsTextEdit> additionalTextEdits;
+ MAKE_SWAP_METHOD(ColorPresentation, label, textEdit, additionalTextEdits)
+};
+MAKE_REFLECT_STRUCT(ColorPresentation, label, textEdit, additionalTextEdits)
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_colorPresentation,
+ ColorPresentationParams, std::vector<ColorPresentation>, "textDocument/colorPresentation") \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/completion.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/completion.h
new file mode 100644
index 0000000000..883c5cfe3a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/completion.h
@@ -0,0 +1,82 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include <regex>
+#include "LibLsp/lsp/lsp_completion.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+
+
+// How a completion was triggered
+enum class lsCompletionTriggerKind {
+ // Completion was triggered by typing an identifier (24x7 code
+ // complete), manual invocation (e.g Ctrl+Space) or via API.
+ Invoked = 1,
+
+ // Completion was triggered by a trigger character specified by
+ // the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
+ TriggerCharacter = 2
+};
+MAKE_REFLECT_TYPE_PROXY(lsCompletionTriggerKind);
+
+
+// Contains additional information about the context in which a completion
+// request is triggered.
+struct lsCompletionContext {
+ // How the completion was triggered.
+ lsCompletionTriggerKind triggerKind = lsCompletionTriggerKind::Invoked;
+
+ // The trigger character (a single character) that has trigger code complete.
+ // Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
+ boost::optional<std::string> triggerCharacter;
+
+ MAKE_SWAP_METHOD(lsCompletionContext, triggerKind, triggerCharacter);
+};
+MAKE_REFLECT_STRUCT(lsCompletionContext, triggerKind, triggerCharacter);
+
+struct lsCompletionParams : lsTextDocumentPositionParams {
+ // The completion context. This is only available it the client specifies to
+ // send this using
+ // `ClientCapabilities.textDocument.completion.contextSupport === true`
+ boost::optional<lsCompletionContext> context;
+
+ MAKE_SWAP_METHOD(lsCompletionParams, textDocument, position, context);
+
+};
+MAKE_REFLECT_STRUCT(lsCompletionParams, textDocument, position, context);
+
+
+
+
+
+
+
+
+
+namespace TextDocumentComplete{
+
+ typedef std::pair< boost::optional<std::vector<lsCompletionItem>>, boost::optional<CompletionList> > Either;
+
+};
+extern void Reflect(Reader& visitor, TextDocumentComplete::Either& value);
+
+/**
+ * The Completion request is sent from the client to the server to compute
+ * completion items at a given cursor position. Completion items are
+ * presented in the IntelliSense user interface. If computing complete
+ * completion items is expensive servers can additional provide a handler
+ * for the resolve completion item request. This request is sent when a
+ * completion item is selected in the user interface.
+ *
+ * Registration Options: CompletionRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_completion, lsCompletionParams, CompletionList , "textDocument/completion")
+
+
+
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/declaration_definition.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/declaration_definition.h
new file mode 100644
index 0000000000..aa20fce046
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/declaration_definition.h
@@ -0,0 +1,29 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "LibLsp/lsp/out_list.h"
+
+
+/**
+ * The go to declaration request is sent from the client to the server to resolve
+ * the declaration location of a symbol at a given text document position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ *
+ * Since version 3.14.0
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_declaration, lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/declaration");
+
+/**
+ * The goto definition request is sent from the client to the server to resolve
+ * the definition location of a symbol at a given text document position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_definition, lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/definition");
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/didRenameFiles.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/didRenameFiles.h
new file mode 100644
index 0000000000..e8a6235a00
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/didRenameFiles.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include <string>
+#include "LibLsp/lsp/CodeActionParams.h"
+#include "LibLsp/lsp/lsWorkspaceEdit.h"
+
+
+class FileRenameEvent {
+public:
+ std::string oldUri;
+ std::string newUri;
+
+ FileRenameEvent() {
+ }
+
+ FileRenameEvent(std::string oldUri, std::string newUri) {
+ this->oldUri = oldUri;
+ this->newUri = newUri;
+ }
+ MAKE_SWAP_METHOD(FileRenameEvent, oldUri, newUri);
+};
+MAKE_REFLECT_STRUCT(FileRenameEvent, oldUri, newUri);
+
+class FileRenameParams {
+public:
+ std::vector <FileRenameEvent> files;
+
+ FileRenameParams() {
+ }
+
+ FileRenameParams(std::vector<FileRenameEvent>& files) {
+ this->files = files;
+ }
+ MAKE_SWAP_METHOD(FileRenameParams, files);
+};
+MAKE_REFLECT_STRUCT(FileRenameParams, files);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_didRenameFiles, FileRenameParams, boost::optional<lsWorkspaceEdit>, "java/didRenameFiles");
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_willRenameFiles, FileRenameParams, boost::optional<lsWorkspaceEdit>, "java/willRenameFiles");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_change.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_change.h
new file mode 100644
index 0000000000..0887bf6602
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_change.h
@@ -0,0 +1,51 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h"
+#include "LibLsp/lsp/lsRange.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+struct lsTextDocumentContentChangeEvent {
+ // The range of the document that changed.
+ boost::optional<lsRange> range;
+ // The length of the range that got replaced.
+ boost::optional<int> rangeLength;
+ // The new text of the range/document.
+ std::string text;
+
+ MAKE_SWAP_METHOD(lsTextDocumentContentChangeEvent, range, rangeLength, text);
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentContentChangeEvent, range, rangeLength, text);
+
+
+struct lsTextDocumentDidChangeParams {
+ lsVersionedTextDocumentIdentifier textDocument;
+ std::vector<lsTextDocumentContentChangeEvent> contentChanges;
+
+ /**
+ * Legacy property to support protocol version 1.0 requests.
+ */
+
+ boost::optional<lsDocumentUri> uri;
+
+ void swap(lsTextDocumentDidChangeParams& arg) noexcept
+ {
+ uri.swap(arg.uri);
+ contentChanges.swap(arg.contentChanges);
+ textDocument.swap(arg.textDocument);
+ }
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentDidChangeParams,
+ textDocument,
+ contentChanges, uri);
+
+/**
+ * The document change notification is sent from the client to the server to
+ * signal changes to a text document.
+ *
+ * Registration Options: TextDocumentChangeRegistrationOptions
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidChange, lsTextDocumentDidChangeParams, "textDocument/didChange");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_close.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_close.h
new file mode 100644
index 0000000000..e2eaa2cfcd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_close.h
@@ -0,0 +1,33 @@
+#pragma once
+
+
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+
+
+
+namespace TextDocumentDidClose {
+
+ struct Params {
+ lsTextDocumentIdentifier textDocument;
+ void swap(Params& arg) noexcept
+ {
+ textDocument.swap(arg.textDocument);
+ }
+
+ };
+
+};
+
+MAKE_REFLECT_STRUCT(TextDocumentDidClose::Params, textDocument);
+
+/**
+ * The document close notification is sent from the client to the server
+ * when the document got closed in the client. The document's truth now
+ * exists where the document's uri points to (e.g. if the document's uri is
+ * a file uri the truth now exists on disk).
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidClose, TextDocumentDidClose::Params, "textDocument/didClose");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_open.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_open.h
new file mode 100644
index 0000000000..7be7a735d6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_open.h
@@ -0,0 +1,39 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+#include "LibLsp/lsp/lsTextDocumentItem.h"
+
+// Open, view, change, close file
+namespace TextDocumentDidOpen {
+
+ struct Params {
+ lsTextDocumentItem textDocument;
+
+
+
+ /**
+ * Legacy property to support protocol version 1.0 requests.
+ */
+ boost::optional<std::string> text;
+
+ MAKE_SWAP_METHOD(TextDocumentDidOpen::Params, textDocument, text);
+
+ };
+
+}
+MAKE_REFLECT_STRUCT(TextDocumentDidOpen::Params, textDocument, text);
+
+/**
+ * The document open notification is sent from the client to the server to
+ * signal newly opened text documents. The document's truth is now managed
+ * by the client and the server must not try to read the document's truth
+ * using the document's uri.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */;
+
+
+DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidOpen, TextDocumentDidOpen::Params, "textDocument/didOpen");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_save.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_save.h
new file mode 100644
index 0000000000..1ce386c415
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/did_save.h
@@ -0,0 +1,31 @@
+#pragma once
+
+
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+
+namespace TextDocumentDidSave {
+
+ struct Params {
+ // The document that was saved.
+ lsTextDocumentIdentifier textDocument;
+
+ // Optional the content when saved. Depends on the includeText value
+ // when the save notifcation was requested.
+ boost::optional<std::string> text;
+
+ MAKE_SWAP_METHOD(TextDocumentDidSave::Params, textDocument, text);
+ };
+
+};
+MAKE_REFLECT_STRUCT(TextDocumentDidSave::Params, textDocument, text);
+
+/**
+ * The document save notification is sent from the client to the server when
+ * the document for saved in the client.
+ *
+ * Registration Options: TextDocumentSaveRegistrationOptions
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidSave, TextDocumentDidSave::Params, "textDocument/didSave");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/documentColor.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/documentColor.h
new file mode 100644
index 0000000000..23a6d08d87
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/documentColor.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+#include "LibLsp/lsp/lsRange.h"
+#include <vector>
+struct DocumentColorParams {
+ /**
+ * The text document.
+ */
+
+ lsTextDocumentIdentifier textDocument;
+ MAKE_SWAP_METHOD(DocumentColorParams, textDocument);
+};
+MAKE_REFLECT_STRUCT(DocumentColorParams, textDocument);
+
+/**
+ * The document color request is sent from the client to the server to list all color references found in a given text
+ * document. Along with the range, a color value in RGB is returned.
+ *
+ * Clients can use the result to decorate color references in an editor. For example:
+ * - Color boxes showing the actual color next to the reference
+ * - Show a color picker when a color reference is edited
+ *
+ * Since version 3.6.0
+ */
+
+namespace TextDocument {
+ struct Color {
+ /**
+ * The red component of this color in the range [0-1].
+ */
+ double red = 0;
+
+ /**
+ * The green component of this color in the range [0-1].
+ */
+ double green = 0;
+
+ /**
+ * The blue component of this color in the range [0-1].
+ */
+ double blue = 0;
+
+ /**
+ * The alpha component of this color in the range [0-1].
+ */
+ double alpha = 0;
+ MAKE_SWAP_METHOD(TextDocument::Color, red, green, blue, alpha)
+ };
+}
+MAKE_REFLECT_STRUCT(TextDocument::Color, red, green, blue, alpha)
+
+
+struct ColorInformation {
+ /**
+ * The range in the document where this color appers.
+ */
+
+ lsRange range;
+
+ /**
+ * The actual color value for this color range.
+ */
+
+ TextDocument::Color color;
+ MAKE_SWAP_METHOD(ColorInformation, range, color)
+};
+MAKE_REFLECT_STRUCT(ColorInformation,range,color)
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_documentColor, DocumentColorParams,std::vector<ColorInformation>, "textDocument/documentColor"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_link.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_link.h
new file mode 100644
index 0000000000..536a625c4c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_link.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+
+namespace TextDocumentDocumentLink {
+
+ struct Params {
+ // The document to provide document links for.
+ lsTextDocumentIdentifier textDocument;
+ MAKE_SWAP_METHOD(Params, textDocument)
+ };
+
+};
+MAKE_REFLECT_STRUCT(TextDocumentDocumentLink::Params, textDocument);
+
+
+
+
+// A document link is a range in a text document that links to an internal or
+// external resource, like another text document or a web site.
+struct lsDocumentLink {
+ // The range this link applies to.
+ lsRange range;
+ // The uri this link points to. If missing a resolve request is sent later.
+ boost::optional<lsDocumentUri> target;
+
+ boost::optional<lsp::Any> data;
+
+ MAKE_SWAP_METHOD(lsDocumentLink, range, target, data)
+
+};
+MAKE_REFLECT_STRUCT(lsDocumentLink, range, target,data);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_links, TextDocumentDocumentLink::Params, lsDocumentLink, "textDocument/documentLink");
+
+
+/**
+ * The document link resolve request is sent from the client to the server to resolve the target of a given document link.
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_linkResolve, std::vector<lsDocumentLink>, lsDocumentLink, "documentLink/resolve");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_symbol.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_symbol.h
new file mode 100644
index 0000000000..8aa6e8b00e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/document_symbol.h
@@ -0,0 +1,55 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/symbol.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+ /**
+ * The document symbol request is sent from the client to the server to list all symbols found in a given text document.
+ */
+struct lsDocumentSymbolParams {
+ lsTextDocumentIdentifier textDocument;
+ MAKE_SWAP_METHOD(lsDocumentSymbolParams, textDocument)
+};
+MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument);
+
+
+
+struct TextDocumentDocumentSymbol{
+ typedef std::pair< boost::optional<lsSymbolInformation> , boost::optional<lsDocumentSymbol> > Either;
+};
+void Reflect(Reader& visitor, TextDocumentDocumentSymbol::Either& value);
+
+
+
+/**
+ * The document symbol request is sent from the client to the server to list all
+ * symbols found in a given text document.
+ *
+ * Registration Options: {@link TextDocumentRegistrationOptions}
+ *
+ * <p>
+ * <b>Caveat</b>: although the return type allows mixing the
+ * {@link DocumentSymbol} and {@link SymbolInformation} instances into a list do
+ * not do it because the clients cannot accept a heterogeneous list. A list of
+ * {@code DocumentSymbol} instances is only a valid return value if the
+ * {@link DocumentSymbolCapabilities#getHierarchicalDocumentSymbolSupport()
+ * textDocument.documentSymbol.hierarchicalDocumentSymbolSupport} is
+ * {@code true}. More details on this difference between the LSP and the LSP4J
+ * can be found <a href="https://github.com/eclipse/lsp4j/issues/252">here</a>.
+ * </p>
+ */
+
+//DEFINE_REQUEST_RESPONSE_TYPE(td_symbol,
+// lsDocumentSymbolParams,
+// std::vector<TextDocumentDocumentSymbol::Either> );
+//
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_symbol,
+ lsDocumentSymbolParams,
+ std::vector< lsDocumentSymbol >,"textDocument/documentSymbol" );
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/foldingRange.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/foldingRange.h
new file mode 100644
index 0000000000..27977a4517
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/foldingRange.h
@@ -0,0 +1,62 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "document_symbol.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+
+struct FoldingRangeRequestParams {
+ /**
+ * The text document.
+ */
+
+ lsTextDocumentIdentifier textDocument;
+ MAKE_SWAP_METHOD(FoldingRangeRequestParams, textDocument)
+};
+MAKE_REFLECT_STRUCT(FoldingRangeRequestParams, textDocument)
+
+
+struct FoldingRange {
+ /**
+ * The zero-based line number from where the folded range starts.
+ */
+ int startLine;
+
+ /**
+ * The zero-based line number where the folded range ends.
+ */
+ int endLine;
+
+ /**
+ * The zero-based character offset from where the folded range starts. If not defined, defaults
+ * to the length of the start line.
+ */
+ int startCharacter;
+
+ /**
+ * The zero-based character offset before the folded range ends. If not defined, defaults to the
+ * length of the end line.
+ */
+ int endCharacter;
+
+ /**
+ * Describes the kind of the folding range such as `comment' or 'region'. The kind
+ * is used to categorize folding ranges and used by commands like 'Fold all comments'. See
+ * FoldingRangeKind for an enumeration of standardized kinds.
+ */
+ std::string kind;
+
+ MAKE_SWAP_METHOD(FoldingRange, startLine, endLine, startCharacter, endCharacter, kind)
+};
+MAKE_REFLECT_STRUCT(FoldingRange,startLine,endLine,startCharacter,endCharacter,kind)
+
+
+/**
+ * The folding range request is sent from the client to the server to return all folding
+ * ranges found in a given text document.
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_foldingRange, FoldingRangeRequestParams, std::vector<FoldingRange>, "textDocument/foldingRange");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/formatting.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/formatting.h
new file mode 100644
index 0000000000..ad54e24bf9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/formatting.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "LibLsp/lsp/lsFormattingOptions.h"
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+
+namespace TextDocumentFormatting {
+
+ struct Params {
+ /**
+ * The document to format.
+ */
+ lsTextDocumentIdentifier textDocument;
+ /**
+ * The format options.
+ */
+ lsFormattingOptions options;
+ MAKE_SWAP_METHOD(Params, textDocument, options);
+ };
+
+};
+MAKE_REFLECT_STRUCT(TextDocumentFormatting::Params, textDocument, options);
+/**
+ * The document formatting request is sent from the client to the server to
+ * format a whole document.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_formatting, TextDocumentFormatting::Params,
+ std::vector<lsTextEdit>, "textDocument/formatting");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/highlight.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/highlight.h
new file mode 100644
index 0000000000..332baf69e1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/highlight.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "document_symbol.h"
+
+/**
+ * The references request is sent from the client to the server to resolve
+ * project-wide references for the symbol denoted by the given text document
+ * position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_highlight, lsTextDocumentPositionParams,
+ std::vector<lsDocumentHighlight>, "textDocument/documentHighlight");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/hover.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/hover.h
new file mode 100644
index 0000000000..5302316c6f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/hover.h
@@ -0,0 +1,55 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsMarkedString.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "LibLsp/lsp/lsRange.h"
+/**
+ * The hover request is sent from the client to the server to request hover
+ * information at a given text document position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+
+namespace TextDocumentHover
+{
+ typedef boost::optional< std::vector< std::pair<boost::optional<std::string>, boost::optional<lsMarkedString>> > > Left;
+ typedef std::pair< Left, boost::optional<MarkupContent> > Either;
+ struct Result {
+ /**
+ * The hover's content as markdown
+ */
+ Either contents;
+
+ /**
+ * An boost::optional range
+ */
+ boost::optional<lsRange> range;
+
+ MAKE_SWAP_METHOD(Result, contents, range)
+ };
+}
+MAKE_REFLECT_STRUCT(TextDocumentHover::Result, contents, range);
+
+extern void Reflect(Reader& visitor, std::pair<boost::optional<std::string>, boost::optional<lsMarkedString>>& value);
+extern void Reflect(Reader& visitor, TextDocumentHover::Either& value);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_hover, lsTextDocumentPositionParams, TextDocumentHover::Result, "textDocument/hover")
+
+//struct Rsp_TextDocumentHover : ResponseMessage< TextDocumentHover::Result, Rsp_TextDocumentHover> {
+//
+//};
+//MAKE_REFLECT_STRUCT(Rsp_TextDocumentHover,
+// jsonrpc,
+// id,
+// result);
+
+//MAKE_REFLECT_STRUCT_OPTIONALS_MANDATORY(Rsp_TextDocumentHover,
+// jsonrpc,
+// id,
+// result);
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/implementation.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/implementation.h
new file mode 100644
index 0000000000..0d7851cb81
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/implementation.h
@@ -0,0 +1,16 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/lsp/out_list.h"
+
+
+/**
+ * The goto implementation request is sent from the client to the server to resolve
+ * the implementation location of a symbol at a given text document position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ *
+ * Since version 3.6.0
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_implementation, lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/implementation"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/linkedEditingRange.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/linkedEditingRange.h
new file mode 100644
index 0000000000..e4055d359f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/linkedEditingRange.h
@@ -0,0 +1,51 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/lsAny.h"
+#include "LibLsp/lsp/symbol.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "LibLsp/lsp/lsRange.h"
+
+
+
+struct LinkedEditingRangeParams
+{
+ lsTextDocumentIdentifier textDocument;
+ lsPosition position;
+
+ MAKE_SWAP_METHOD(LinkedEditingRangeParams,
+ textDocument,
+ position)
+};
+MAKE_REFLECT_STRUCT(LinkedEditingRangeParams,
+ textDocument,
+ position)
+
+
+struct LinkedEditingRanges
+{
+ /**
+ * A list of ranges that can be renamed together. The ranges must have
+ * identical length and contain identical text content. The ranges cannot overlap.
+ */
+ std::vector<lsRange> ranges;
+
+ /**
+ * An optional word pattern (regular expression) that describes valid contents for
+ * the given ranges. If no pattern is provided, the client configuration's word
+ * pattern will be used.
+ */
+
+ boost::optional<std::string> wordPattern;
+ MAKE_SWAP_METHOD(LinkedEditingRanges,
+ ranges,
+ wordPattern)
+};
+
+MAKE_REFLECT_STRUCT(LinkedEditingRanges,
+ ranges,
+ wordPattern)
+DEFINE_REQUEST_RESPONSE_TYPE(td_linkedEditingRange, LinkedEditingRangeParams,
+ boost::optional<std::vector<LinkedEditingRanges >>,"textDocument/linkedEditingRange") \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/onTypeFormatting.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/onTypeFormatting.h
new file mode 100644
index 0000000000..df14ea5d3d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/onTypeFormatting.h
@@ -0,0 +1,44 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsFormattingOptions.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+#include "LibLsp/lsp/lsRange.h"
+#include "LibLsp/lsp/lsTextEdit.h"
+
+
+struct lsDocumentOnTypeFormattingParams
+{
+ lsTextDocumentIdentifier textDocument;
+ lsFormattingOptions options;
+
+ lsPosition position;
+
+ /**
+ * The character that has been typed.
+ */
+
+ std::string ch;
+
+ MAKE_SWAP_METHOD(lsDocumentOnTypeFormattingParams,
+ textDocument,
+ position,
+ options, ch);
+};
+MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingParams,
+ textDocument,
+ position,
+ options,ch);
+
+/**
+ * The document range formatting request is sent from the client to the
+ * server to format a given range in a document.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_onTypeFormatting,
+ lsDocumentOnTypeFormattingParams, std::vector<lsTextEdit>, "textDocument/onTypeFormatting");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/prepareRename.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/prepareRename.h
new file mode 100644
index 0000000000..8c653d9864
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/prepareRename.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsWorkspaceEdit.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+
+/**
+ * The rename request is sent from the client to the server to do a
+ * workspace wide rename of a symbol.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+struct PrepareRenameResult{
+ /**
+ * The range of the string to rename
+ */
+
+ lsRange range;
+
+/**
+ * A placeholder text of the string content to be renamed.
+ */
+
+ std::string placeholder;
+
+ MAKE_SWAP_METHOD(PrepareRenameResult, range, placeholder)
+
+};
+MAKE_REFLECT_STRUCT(PrepareRenameResult,range,placeholder)
+
+
+
+typedef std::pair< boost::optional< lsRange>, boost::optional<PrepareRenameResult>> TextDocumentPrepareRenameResult;
+extern void Reflect(Reader& visitor, TextDocumentPrepareRenameResult& value);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_prepareRename,
+ lsTextDocumentPositionParams, TextDocumentPrepareRenameResult, "textDocument/prepareRename"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/publishDiagnostics.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/publishDiagnostics.h
new file mode 100644
index 0000000000..bf28104bbb
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/publishDiagnostics.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/lsp/lsp_diagnostic.h"
+
+// Diagnostics
+namespace TextDocumentPublishDiagnostics{
+ struct Params {
+ // The URI for which diagnostic information is reported.
+ lsDocumentUri uri;
+
+ // An array of diagnostic information items.
+ std::vector<lsDiagnostic> diagnostics;
+ MAKE_SWAP_METHOD(Params,uri,diagnostics);
+ };
+
+
+};
+MAKE_REFLECT_STRUCT(TextDocumentPublishDiagnostics::Params,
+ uri,
+ diagnostics);
+
+/**
+ * Diagnostics notifications are sent from the server to the client to
+ * signal results of validation runs.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentPublishDiagnostics, TextDocumentPublishDiagnostics::Params, "textDocument/publishDiagnostics");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/range_formatting.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/range_formatting.h
new file mode 100644
index 0000000000..b2fe750af1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/range_formatting.h
@@ -0,0 +1,35 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsFormattingOptions.h"
+
+
+struct lsTextDocumentRangeFormattingParams {
+ lsTextDocumentIdentifier textDocument;
+ lsRange range;
+ lsFormattingOptions options;
+
+ MAKE_SWAP_METHOD(lsTextDocumentRangeFormattingParams,
+ textDocument,
+ range,
+ options)
+};
+MAKE_REFLECT_STRUCT(lsTextDocumentRangeFormattingParams,
+ textDocument,
+ range,
+ options);
+
+/**
+ * The document range formatting request is sent from the client to the
+ * server to format a given range in a document.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_rangeFormatting, lsTextDocumentRangeFormattingParams, std::vector<lsTextEdit>,
+ "textDocument/rangeFormatting");
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/references.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/references.h
new file mode 100644
index 0000000000..2376912756
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/references.h
@@ -0,0 +1,48 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/symbol.h"
+
+
+namespace TextDocumentReferences {
+
+ struct lsReferenceContext {
+ // Include the declaration of the current symbol.
+ boost::optional<bool> includeDeclaration;
+ MAKE_REFLECT_STRUCT(lsReferenceContext,
+ includeDeclaration)
+ };
+ struct Params {
+ lsTextDocumentIdentifier textDocument;
+ lsPosition position;
+ lsReferenceContext context;
+ MAKE_SWAP_METHOD(Params,
+ textDocument,
+ position,
+ context)
+
+ };
+
+};
+MAKE_REFLECT_STRUCT(TextDocumentReferences::lsReferenceContext,
+ includeDeclaration);
+MAKE_REFLECT_STRUCT(TextDocumentReferences::Params,
+ textDocument,
+ position,
+ context);
+
+
+
+
+/**
+ * The references request is sent from the client to the server to resolve
+ * project-wide references for the symbol denoted by the given text document
+ * position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_references, TextDocumentReferences::Params,
+ std::vector<lsLocation>, "textDocument/references");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/rename.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/rename.h
new file mode 100644
index 0000000000..35895f0f4f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/rename.h
@@ -0,0 +1,41 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsWorkspaceEdit.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+namespace TextDocumentRename {
+
+ struct Params {
+ // The document to format.
+ lsTextDocumentIdentifier textDocument;
+
+ // The position at which this request was sent.
+ lsPosition position;
+
+ // The new name of the symbol. If the given name is not valid the
+ // request must return a [ResponseError](#ResponseError) with an
+ // appropriate message set.
+ std::string newName;
+ MAKE_SWAP_METHOD(Params,
+ textDocument,
+ position,
+ newName);
+ };
+
+};
+MAKE_REFLECT_STRUCT(TextDocumentRename::Params,
+ textDocument,
+ position,
+ newName);
+/**
+ * The rename request is sent from the client to the server to do a
+ * workspace wide rename of a symbol.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_rename, TextDocumentRename::Params, lsWorkspaceEdit, "textDocument/rename");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCodeLens.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCodeLens.h
new file mode 100644
index 0000000000..0723985160
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCodeLens.h
@@ -0,0 +1,10 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "code_lens.h"
+
+DEFINE_REQUEST_RESPONSE_TYPE(codeLens_resolve, lsCodeLens, lsCodeLens, "codeLens/resolve")
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCompletionItem.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCompletionItem.h
new file mode 100644
index 0000000000..f5576894ed
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveCompletionItem.h
@@ -0,0 +1,21 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include <regex>
+#include "LibLsp/lsp/lsp_completion.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "completion.h"
+
+/**
+ * The request is sent from the client to the server to resolve additional
+ * information for a given completion item.
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(completionItem_resolve, lsCompletionItem, lsCompletionItem, "completionItem/resolve");
+
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveTypeHierarchy.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveTypeHierarchy.h
new file mode 100644
index 0000000000..eab5f838fc
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/resolveTypeHierarchy.h
@@ -0,0 +1,31 @@
+#pragma once
+
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/symbol.h"
+#include "typeHierarchy.h"
+
+struct ResolveTypeHierarchyItemParams {
+ /**
+ * The hierarchy item to resolve.
+ */
+
+ TypeHierarchyItem item;
+
+ /**
+ * The number of hierarchy levels to resolve. {@code 0} indicates no hierarchy level.
+ */
+ boost::optional<int> resolve;
+
+ /**
+ * The direction of the type hierarchy resolution.
+ */
+
+ TypeHierarchyDirection direction;
+ MAKE_SWAP_METHOD(ResolveTypeHierarchyItemParams, item, resolve, direction)
+};
+MAKE_REFLECT_STRUCT(ResolveTypeHierarchyItemParams,item,resolve,direction)
+DEFINE_REQUEST_RESPONSE_TYPE(typeHierarchy_resolve, ResolveTypeHierarchyItemParams, TypeHierarchyItem, "typeHierarchy/resolve")
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/selectionRange.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/selectionRange.h
new file mode 100644
index 0000000000..47590e4152
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/selectionRange.h
@@ -0,0 +1,52 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsPosition.h"
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+struct SelectionRangeParams {
+ /**
+ * The text document.
+ */
+
+ lsTextDocumentIdentifier textDocument;
+
+ /**
+ * The positions inside the text document.
+ */
+
+ std::vector<lsPosition> positions;
+
+ MAKE_SWAP_METHOD(SelectionRangeParams, textDocument, positions)
+
+};
+MAKE_REFLECT_STRUCT(SelectionRangeParams, textDocument, positions)
+
+struct SelectionRange {
+ /**
+ * The [range](#Range) of this selection range.
+ */
+
+ lsRange range;
+
+ /**
+ * The parent selection range containing this range. Therefore `parent.range` must contain `this.range`.
+ */
+ boost::optional<SelectionRange*> parent;
+ MAKE_SWAP_METHOD(SelectionRange, range, parent)
+};
+
+extern void Reflect(Reader& visitor, boost::optional<SelectionRange*>& value);
+extern void Reflect(Writer& visitor, SelectionRange* value);
+
+MAKE_REFLECT_STRUCT(SelectionRange,range,parent)
+/**
+ * The {@code textDocument/selectionRange} request is sent from the client to the server to return
+ * suggested selection ranges at an array of given positions. A selection range is a range around
+ * the cursor position which the user might be interested in selecting.
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_selectionRange, SelectionRangeParams, std::vector<SelectionRange>, "textDocument/selectionRange");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/semanticHighlighting.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/semanticHighlighting.h
new file mode 100644
index 0000000000..32bc86f5fb
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/semanticHighlighting.h
@@ -0,0 +1,66 @@
+#pragma once
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h"
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+/**
+ * Represents a semantic highlighting information that has to be applied on a specific line of the text document.
+ */
+
+struct SemanticHighlightingInformation {
+ /**
+ * The zero-based line position in the text document.
+ */
+ int line = 0;
+
+ /**
+ * A base64 encoded string representing every single highlighted ranges in the line with its start position, length
+ * and the "lookup table" index of of the semantic highlighting <a href="https://manual.macromates.com/en/language_grammars">
+ * TextMate scopes</a>. If the {@code tokens} is empty or not defined, then no highlighted positions are available for the line.
+ */
+ std::string tokens;
+
+ MAKE_SWAP_METHOD(SemanticHighlightingInformation, line, tokens)
+};
+
+MAKE_REFLECT_STRUCT(SemanticHighlightingInformation, line, tokens);
+
+/**
+ * Parameters for the semantic highlighting (server-side) push notification.
+ */
+
+struct SemanticHighlightingParams {
+ /**
+ * The text document that has to be decorated with the semantic highlighting information.
+ */
+
+ lsVersionedTextDocumentIdentifier textDocument;
+
+ /**
+ * An array of semantic highlighting information.
+ */
+
+ std::vector<SemanticHighlightingInformation> lines;
+
+ MAKE_SWAP_METHOD(SemanticHighlightingParams, textDocument, lines)
+
+};
+MAKE_REFLECT_STRUCT(SemanticHighlightingParams, textDocument, lines);
+/**
+ * The {@code textDocument/semanticHighlighting} notification is pushed from the server to the client
+ * to inform the client about additional semantic highlighting information that has to be applied
+ * on the text document. It is the server's responsibility to decide which lines are included in
+ * the highlighting information. In other words, the server is capable of sending only a delta
+ * information. For instance, after opening the text document ({@code DidOpenTextDocumentNotification})
+ * the server sends the semantic highlighting information for the entire document, but if the server
+ * receives a {@code DidChangeTextDocumentNotification}, it pushes the information only about
+ * the affected lines in the document.
+ *
+ * <p>
+ * <b>Note:</b> the <a href=
+ * "https://github.com/Microsoft/vscode-languageserver-node/pull/367">{@code textDocument/semanticHighlighting}
+ * language feature</a> is not yet part of the official LSP specification.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_semanticHighlighting, SemanticHighlightingParams, "textDocument/semanticHighlighting"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/signature_help.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/signature_help.h
new file mode 100644
index 0000000000..2a83645901
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/signature_help.h
@@ -0,0 +1,92 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/lsMarkedString.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+
+extern void Reflect(Reader& visitor,
+ std::pair<boost::optional<std::string>, boost::optional<MarkupContent>>& value);
+
+
+
+// Represents a parameter of a callable-signature. A parameter can
+// have a label and a doc-comment.
+struct lsParameterInformation {
+ // The label of this parameter. Will be shown in
+ // the UI.
+ std::string label;
+
+ // The human-readable doc-comment of this parameter. Will be shown
+ // in the UI but can be omitted.
+ boost::optional< std::pair< boost::optional<std::string> , boost::optional <MarkupContent> > > documentation;
+
+ MAKE_SWAP_METHOD(lsParameterInformation, label, documentation)
+};
+MAKE_REFLECT_STRUCT(lsParameterInformation, label, documentation);
+
+// Represents the signature of something callable. A signature
+// can have a label, like a function-name, a doc-comment, and
+// a set of parameters.
+struct lsSignatureInformation {
+ // The label of this signature. Will be shown in
+ // the UI.
+ std::string label;
+
+ // The human-readable doc-comment of this signature. Will be shown
+ // in the UI but can be omitted.
+ boost::optional< std::pair< boost::optional<std::string>, boost::optional <MarkupContent> > > documentation;
+
+ // The parameters of this signature.
+ std::vector<lsParameterInformation> parameters;
+
+ MAKE_SWAP_METHOD(lsSignatureInformation, label, documentation, parameters)
+};
+MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters);
+
+// Signature help represents the signature of something
+// callable. There can be multiple signature but only one
+// active and only one active parameter.
+struct lsSignatureHelp {
+ // One or more signatures.
+ std::vector<lsSignatureInformation> signatures;
+
+ // The active signature. If omitted or the value lies outside the
+ // range of `signatures` the value defaults to zero or is ignored if
+ // `signatures.length === 0`. Whenever possible implementors should
+ // make an active decision about the active signature and shouldn't
+ // rely on a default value.
+ // In future version of the protocol this property might become
+ // mandantory to better express this.
+ boost::optional<int> activeSignature;
+
+ // The active parameter of the active signature. If omitted or the value
+ // lies outside the range of `signatures[activeSignature].parameters`
+ // defaults to 0 if the active signature has parameters. If
+ // the active signature has no parameters it is ignored.
+ // In future version of the protocol this property might become
+ // mandantory to better express the active parameter if the
+ // active signature does have any.
+ boost::optional<int> activeParameter;
+
+
+ MAKE_SWAP_METHOD(lsSignatureHelp,
+ signatures,
+ activeSignature,
+ activeParameter)
+};
+MAKE_REFLECT_STRUCT(lsSignatureHelp,
+ signatures,
+ activeSignature,
+ activeParameter);
+
+
+
+/**
+ * The signature help request is sent from the client to the server to
+ * request signature information at a given cursor position.
+ *
+ * Registration Options: SignatureHelpRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_signatureHelp, lsTextDocumentPositionParams, lsSignatureHelp, "textDocument/signatureHelp"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/textDocument.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/textDocument.cpp
new file mode 100644
index 0000000000..32f647436d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/textDocument.cpp
@@ -0,0 +1,349 @@
+#include "completion.h"
+#include "document_symbol.h"
+#include "LibLsp/lsp/lsMarkedString.h"
+#include "hover.h"
+#include "prepareRename.h"
+#include <LibLsp/lsp/textDocument/typeHierarchy.h>
+
+#include "semanticHighlighting.h"
+#include "SemanticTokens.h"
+#include "LibLsp/JsonRpc/json.h"
+
+
+constexpr unsigned SemanticTokenEncodingSize = 5;
+
+std::string to_string(SemanticTokenType _type)
+{
+ switch (_type) {
+
+ case ls_namespace: return "namespace";
+ /**
+ * Represents a generic type. Acts as a fallback for types which
+ * can"t be mapped to a specific type like class or enum.
+ */
+ case ls_type: return "type";
+ case ls_class: return "class";
+ case ls_enum: return "enum";
+ case ls_interface: return "interface";
+ case ls_struct: return "struct";
+ case ls_typeParameter: return "typeParameter";
+ case ls_parameter: return "parameter";
+ case ls_variable: return "variable";
+ case ls_property: return "property";
+ case ls_enumMember: return "enumMember";
+ case ls_event: return "event";
+ case ls_function: return "function";
+ case ls_method: return "method";
+ case ls_macro: return "macro";
+ case ls_keyword: return "keyword";
+ case ls_modifier: return "modifier";
+ case ls_comment: return "comment";
+ case ls_string: return "string";
+ case ls_number: return "number";
+ case ls_regexp: return "regexp";
+ case ls_operator: return "operator";
+ default:
+ return "unknown";
+ }
+}
+
+unsigned toSemanticTokenType(std::vector<SemanticTokenType>& modifiers)
+{
+ unsigned encode_type = 0;
+ for (auto bit : modifiers) {
+ encode_type = encode_type | (0b00000001 << bit);
+ }
+ return encode_type;
+}
+
+std::string to_string(TokenType_JDT _type)
+{
+ switch (_type)
+ {
+ case PACKAGE_JDT:return "namespace";
+ case CLASS_JDT:return "class";
+ case INTERFACE_JDT:return "interface";
+ case ENUM_JDT:return "enum";
+ case ENUM_MEMBER_JDT:return "enumMember";
+ case TYPE_JDT:return "type";
+ case TYPE_PARAMETER_JDT:return "typeParameter";
+ case ANNOTATION_JDT:return "annotation";
+ case ANNOTATION_MEMBER_JDT:return "annotationMember";
+ case METHOD_JDT:return "function";
+ case PROPERTY_JDT:return "property";
+ case VARIABLE_JDT:return "variable";
+ case PARAMETER_JDT:return "parameter";
+ }
+ return "unknown";
+}
+
+std::string to_string(SemanticTokenModifier modifier)
+{
+ switch (modifier) {
+ case ls_declaration: return "declaration";
+ case ls_definition: return "definition";
+ case ls_readonly: return "readonly";
+ case ls_static: return "static";
+ case ls_deprecated: return "deprecated";
+ case ls_abstract: return "abstract";
+ case ls_async: return "async";
+ case ls_modification: return "modification";
+ case ls_documentation: return "documentation";
+ case ls_defaultLibrary: return "defaultLibrary";
+ default:
+ return "unknown";
+ }
+}
+
+unsigned toSemanticTokenModifiers(std::vector<SemanticTokenModifier>& modifiers)
+{
+ unsigned encodedModifiers = 0;
+ for (auto bit : modifiers) {
+ encodedModifiers = encodedModifiers | (0b00000001 << bit);
+ }
+ return encodedModifiers;
+}
+
+
+std::string toSemanticTokenType(HighlightingKind_clangD kind) {
+ switch (kind) {
+ case HighlightingKind_clangD::Variable:
+ case HighlightingKind_clangD::LocalVariable:
+ case HighlightingKind_clangD::StaticField:
+ return "variable";
+ case HighlightingKind_clangD::Parameter:
+ return "parameter";
+ case HighlightingKind_clangD::Function:
+ return "function";
+ case HighlightingKind_clangD::Method:
+ return "method";
+ case HighlightingKind_clangD::StaticMethod:
+ // FIXME: better method with static modifier?
+ return "function";
+ case HighlightingKind_clangD::Field:
+ return "property";
+ case HighlightingKind_clangD::Class:
+ return "class";
+ case HighlightingKind_clangD::Interface:
+ return "interface";
+ case HighlightingKind_clangD::Enum:
+ return "enum";
+ case HighlightingKind_clangD::EnumConstant:
+ return "enumMember";
+ case HighlightingKind_clangD::Typedef:
+ case HighlightingKind_clangD::Type:
+ return "type";
+ case HighlightingKind_clangD::Unknown:
+ return "unknown"; // nonstandard
+ case HighlightingKind_clangD::Namespace:
+ return "namespace";
+ case HighlightingKind_clangD::TemplateParameter:
+ return "typeParameter";
+ case HighlightingKind_clangD::Concept:
+ return "concept"; // nonstandard
+ case HighlightingKind_clangD::Primitive:
+ return "type";
+ case HighlightingKind_clangD::Macro:
+ return "macro";
+ case HighlightingKind_clangD::InactiveCode:
+ return "comment";
+ }
+ return ("unhandled HighlightingKind_clangD");
+}
+
+std::string toSemanticTokenModifier(HighlightingModifier_clangD modifier) {
+ switch (modifier) {
+ case HighlightingModifier_clangD::Declaration:
+ return "declaration";
+ case HighlightingModifier_clangD::Deprecated:
+ return "deprecated";
+ case HighlightingModifier_clangD::Readonly:
+ return "readonly";
+ case HighlightingModifier_clangD::Static:
+ return "static";
+ case HighlightingModifier_clangD::Deduced:
+ return "deduced"; // nonstandard
+ case HighlightingModifier_clangD::Abstract:
+ return "abstract";
+ case HighlightingModifier_clangD::DependentName:
+ return "dependentName"; // nonstandard
+ case HighlightingModifier_clangD::DefaultLibrary:
+ return "defaultLibrary";
+ case HighlightingModifier_clangD::FunctionScope:
+ return "functionScope"; // nonstandard
+ case HighlightingModifier_clangD::ClassScope:
+ return "classScope"; // nonstandard
+ case HighlightingModifier_clangD::FileScope:
+ return "fileScope"; // nonstandard
+ case HighlightingModifier_clangD::GlobalScope:
+ return "globalScope"; // nonstandard
+ }
+ return ("unhandled HighlightingModifier_clangD");
+}
+
+
+
+bool operator==(const SemanticToken& l, const SemanticToken& r) {
+ return std::tie(l.deltaLine, l.deltaStart, l.length, l.tokenType,
+ l.tokenModifiers) == std::tie(r.deltaLine, r.deltaStart,
+ r.length, r.tokenType,
+ r.tokenModifiers);
+}
+
+std::vector<int32_t> SemanticTokens::encodeTokens(std::vector<SemanticToken>& tokens)
+{
+ std::vector<int32_t> result;
+ result.reserve(SemanticTokenEncodingSize * tokens.size());
+ for (const auto& tok : tokens)
+ {
+ result.push_back(tok.deltaLine);
+ result.push_back(tok.deltaStart);
+ result.push_back(tok.length);
+ result.push_back(tok.tokenType);
+ result.push_back(tok.tokenModifiers);
+ }
+ assert(result.size() == SemanticTokenEncodingSize * tokens.size());
+ return result;
+}
+
+void Reflect(Reader& visitor, TextDocumentComplete::Either& value)
+{
+ if(visitor.IsArray())
+ {
+ Reflect(visitor, value.first);
+ }
+ else
+ {
+
+ Reflect(visitor, value.second);
+ }
+
+}
+void Reflect(Reader& visitor, TextDocumentDocumentSymbol::Either& value)
+{
+ if (visitor.HasMember("location"))
+ {
+ Reflect(visitor, value.first);
+ }
+ else
+ {
+ Reflect(visitor, value.second);
+ }
+}
+
+void Reflect(Reader& visitor, std::pair<boost::optional<std::string>, boost::optional<lsMarkedString>>& value)
+{
+
+ if (!visitor.IsString())
+ {
+ Reflect(visitor, value.second);
+ }
+ else
+ {
+ Reflect(visitor, value.first);
+ }
+}
+
+void Reflect(Reader& visitor, std::pair<boost::optional<std::string>, boost::optional<MarkupContent>>& value)
+{
+ if (!visitor.IsString())
+ {
+ Reflect(visitor, value.second);
+ }
+ else
+ {
+ Reflect(visitor, value.first);
+ }
+}
+ void Reflect(Reader& visitor, TextDocumentHover::Either& value)
+{
+ JsonReader& reader = dynamic_cast<JsonReader&>(visitor);
+ if (reader.IsArray())
+ {
+ Reflect(visitor, value.first);
+ }
+ else if(reader.m_->IsObject())
+ {
+ Reflect(visitor, value.second);
+ }
+}
+
+ void Reflect(Reader& visitor, TextDocumentPrepareRenameResult& value)
+{
+ if (visitor.HasMember("placeholder"))
+ {
+ Reflect(visitor, value.second);
+ }
+ else
+ {
+ Reflect(visitor, value.first);
+ }
+}
+
+ namespace
+ RefactorProposalUtility
+ {
+ const char* APPLY_REFACTORING_COMMAND_ID = "java.action.applyRefactoringCommand";
+ const char* EXTRACT_VARIABLE_ALL_OCCURRENCE_COMMAND = "extractVariableAllOccurrence";
+ const char* EXTRACT_VARIABLE_COMMAND = "extractVariable";
+ const char* EXTRACT_CONSTANT_COMMAND = "extractConstant";
+ const char* EXTRACT_METHOD_COMMAND = "extractMethod";
+ const char* EXTRACT_FIELD_COMMAND = "extractField";
+ const char* CONVERT_VARIABLE_TO_FIELD_COMMAND = "convertVariableToField";
+ const char* MOVE_FILE_COMMAND = "moveFile";
+ const char* MOVE_INSTANCE_METHOD_COMMAND = "moveInstanceMethod";
+ const char* MOVE_STATIC_MEMBER_COMMAND = "moveStaticMember";
+ const char* MOVE_TYPE_COMMAND = "moveType";
+ };
+ namespace QuickAssistProcessor {
+
+ const char* SPLIT_JOIN_VARIABLE_DECLARATION_ID = "org.eclipse.jdt.ls.correction.splitJoinVariableDeclaration.assist"; //$NON-NLS-1$
+ const char* CONVERT_FOR_LOOP_ID = "org.eclipse.jdt.ls.correction.convertForLoop.assist"; //$NON-NLS-1$
+ const char* ASSIGN_TO_LOCAL_ID = "org.eclipse.jdt.ls.correction.assignToLocal.assist"; //$NON-NLS-1$
+ const char* ASSIGN_TO_FIELD_ID = "org.eclipse.jdt.ls.correction.assignToField.assist"; //$NON-NLS-1$
+ const char* ASSIGN_PARAM_TO_FIELD_ID = "org.eclipse.jdt.ls.correction.assignParamToField.assist"; //$NON-NLS-1$
+ const char* ASSIGN_ALL_PARAMS_TO_NEW_FIELDS_ID = "org.eclipse.jdt.ls.correction.assignAllParamsToNewFields.assist"; //$NON-NLS-1$
+ const char* ADD_BLOCK_ID = "org.eclipse.jdt.ls.correction.addBlock.assist"; //$NON-NLS-1$
+ const char* EXTRACT_LOCAL_ID = "org.eclipse.jdt.ls.correction.extractLocal.assist"; //$NON-NLS-1$
+ const char* EXTRACT_LOCAL_NOT_REPLACE_ID = "org.eclipse.jdt.ls.correction.extractLocalNotReplaceOccurrences.assist"; //$NON-NLS-1$
+ const char* EXTRACT_CONSTANT_ID = "org.eclipse.jdt.ls.correction.extractConstant.assist"; //$NON-NLS-1$
+ const char* INLINE_LOCAL_ID = "org.eclipse.jdt.ls.correction.inlineLocal.assist"; //$NON-NLS-1$
+ const char* CONVERT_LOCAL_TO_FIELD_ID = "org.eclipse.jdt.ls.correction.convertLocalToField.assist"; //$NON-NLS-1$
+ const char* CONVERT_ANONYMOUS_TO_LOCAL_ID = "org.eclipse.jdt.ls.correction.convertAnonymousToLocal.assist"; //$NON-NLS-1$
+ const char* CONVERT_TO_STRING_BUFFER_ID = "org.eclipse.jdt.ls.correction.convertToStringBuffer.assist"; //$NON-NLS-1$
+ const char* CONVERT_TO_MESSAGE_FORMAT_ID = "org.eclipse.jdt.ls.correction.convertToMessageFormat.assist"; //$NON-NLS-1$;
+ const char* EXTRACT_METHOD_INPLACE_ID = "org.eclipse.jdt.ls.correction.extractMethodInplace.assist"; //$NON-NLS-1$;
+
+ const char* CONVERT_ANONYMOUS_CLASS_TO_NESTED_COMMAND = "convertAnonymousClassToNestedCommand";
+ };
+
+ void Reflect(Reader& reader, TypeHierarchyDirection& value) {
+ if (!reader.IsString())
+ {
+ value = TypeHierarchyDirection::Both;
+ return;
+ }
+ std::string v = reader.GetString();
+ if (v == "Children")
+ value = TypeHierarchyDirection::Both;
+ else if (v == "Parents")
+ value = TypeHierarchyDirection::Parents;
+ else if (v == "Both")
+ value = TypeHierarchyDirection::Both;
+ }
+
+
+ void Reflect(Writer& writer, TypeHierarchyDirection& value) {
+ switch (value)
+ {
+ case TypeHierarchyDirection::Children:
+ writer.String("Children");
+ break;
+ case TypeHierarchyDirection::Parents:
+ writer.String("Parents");
+ break;
+ case TypeHierarchyDirection::Both:
+ writer.String("Both");
+ break;
+ }
+ }
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/typeHierarchy.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/typeHierarchy.h
new file mode 100644
index 0000000000..b554d751f3
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/typeHierarchy.h
@@ -0,0 +1,133 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+#include "LibLsp/lsp/lsTextDocumentPositionParams.h"
+#include "LibLsp/lsp/symbol.h"
+#include "LibLsp/lsp/lsAny.h"
+/**
+ * The {@code textDocument/typeHierarchy} request is sent from the client to the
+ * server to retrieve a {@link TypeHierarchyItem type hierarchy item} based on
+ * the {@link TypeHierarchyParams cursor position in the text document}. This
+ * request would also allow to specify if the item should be resolved and
+ * whether sub- or supertypes are to be resolved. If no type hierarchy item can
+ * be found under the given text document position, resolves to {@code null}.
+ *
+ * <p>
+ * <b>Note:</b> the <a href=
+ * "https://github.com/Microsoft/vscode-languageserver-node/pull/426">{@code textDocument/typeHierarchy}
+ * language feature</a> is not yet part of the official LSP specification.
+ */
+enum class TypeHierarchyDirection : uint32_t{
+
+ /**
+ * Flag for retrieving/resolving the subtypes. Value: {@code 0}.
+ */
+ Children = 0,
+
+ /**
+ * Flag to use when retrieving/resolving the supertypes. Value: {@code 1}.
+ */
+ Parents =1,
+
+ /**
+ * Flag for resolving both the super- and subtypes. Value: {@code 2}.
+ */
+ Both=2
+};
+void Reflect(Reader& reader, TypeHierarchyDirection& value);
+
+
+void Reflect(Writer& writer, TypeHierarchyDirection& value);
+
+struct TypeHierarchyParams :public lsTextDocumentPositionParams
+{
+ boost::optional<int> resolve;
+ boost::optional<TypeHierarchyDirection> direction ;
+
+ MAKE_SWAP_METHOD(TypeHierarchyParams, textDocument, position, resolve, direction)
+};
+MAKE_REFLECT_STRUCT(TypeHierarchyParams, textDocument, position, resolve, direction);
+
+
+
+
+
+/**
+ * Representation of an item that carries type information (such as class, interface, enumeration, etc) with additional parentage details.
+ */
+
+struct TypeHierarchyItem {
+ /**
+ * The human readable name of the hierarchy item.
+ */
+
+ std::string name;
+
+ /**
+ * Optional detail for the hierarchy item. It can be, for instance, the signature of a function or method.
+ */
+ boost::optional<std::string>
+ detail;
+
+ /**
+ * The kind of the hierarchy item. For instance, class or interface.
+ */
+
+ SymbolKind kind;
+
+ /**
+ * {@code true} if the hierarchy item is deprecated. Otherwise, {@code false}. It is {@code false} by default.
+ */
+
+ boost::optional<bool> deprecated;
+
+ /**
+ * The URI of the text document where this type hierarchy item belongs to.
+ */
+
+ lsDocumentUri uri;
+
+ /**
+ * The range enclosing this type hierarchy item not including leading/trailing whitespace but everything else
+ * like comments. This information is typically used to determine if the clients cursor is inside the type
+ * hierarchy item to reveal in the symbol in the UI.
+ *
+ * @see TypeHierarchyItem#selectionRange
+ */
+
+ lsRange range;
+
+ /**
+ * The range that should be selected and revealed when this type hierarchy item is being picked, e.g the name of a function.
+ * Must be contained by the the {@link TypeHierarchyItem#getRange range}.
+ *
+ * @see TypeHierarchyItem#range
+ */
+
+ lsRange selectionRange;
+
+ /**
+ * If this type hierarchy item is resolved, it contains the direct parents. Could be empty if the item does not have any
+ * direct parents. If not defined, the parents have not been resolved yet.
+ */
+ boost::optional< std::vector<TypeHierarchyItem> > parents;
+
+ /**
+ * If this type hierarchy item is resolved, it contains the direct children of the current item.
+ * Could be empty if the item does not have any descendants. If not defined, the children have not been resolved.
+ */
+ boost::optional< std::vector<TypeHierarchyItem> > children;
+
+ /**
+ * An boost::optional data field can be used to identify a type hierarchy item in a resolve request.
+ */
+ boost::optional<lsp::Any> data;
+
+ MAKE_SWAP_METHOD(TypeHierarchyItem, name, detail, kind, deprecated, uri, range, selectionRange, parents, children, data)
+};
+MAKE_REFLECT_STRUCT(TypeHierarchyItem, name, detail, kind, deprecated, uri, range, selectionRange, parents, children, data);
+
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(td_typeHierarchy, TypeHierarchyParams, TypeHierarchyItem, "textDocument/typeHierarchy"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/type_definition.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/type_definition.h
new file mode 100644
index 0000000000..38ced43b42
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/type_definition.h
@@ -0,0 +1,16 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/lsp/out_list.h"
+
+/**
+ * The goto type definition request is sent from the client to the server to resolve
+ * the type definition location of a symbol at a given text document position.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ *
+ * Since version 3.6.0
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_typeDefinition,
+ lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/typeDefinition"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/willSave.h b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/willSave.h
new file mode 100644
index 0000000000..84aa0badaa
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/textDocument/willSave.h
@@ -0,0 +1,71 @@
+#pragma once
+
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsTextDocumentIdentifier.h"
+
+namespace WillSaveTextDocumentParams {
+
+ /**
+ * Represents reasons why a text document is saved.
+ */
+ enum class TextDocumentSaveReason {
+
+ /**
+ * Manually triggered, e.g. by the user pressing save, by starting debugging,
+ * or by an API call.
+ */
+ Manual=(1),
+
+ /**
+ * Automatic after a delay.
+ */
+ AfterDelay=(2),
+
+ /**
+ * When the editor lost focus.
+ */
+ FocusOut=(3)
+ };
+
+ struct Params {
+ /**
+ * The document that will be saved.
+ */
+ lsTextDocumentIdentifier textDocument;
+
+ /*
+ * A reason why a text document is saved.
+ */
+
+ boost::optional<TextDocumentSaveReason> reason;
+
+ MAKE_SWAP_METHOD(Params, textDocument, reason);
+ };
+
+};
+MAKE_REFLECT_TYPE_PROXY(WillSaveTextDocumentParams::TextDocumentSaveReason);
+
+MAKE_REFLECT_STRUCT(WillSaveTextDocumentParams::Params, textDocument, reason);
+
+/**
+ * The document save notification is sent from the client to the server when
+ * the document for saved in the client.
+ *
+ * Registration Options: TextDocumentSaveRegistrationOptions
+ */
+DEFINE_NOTIFICATION_TYPE(td_willSave, WillSaveTextDocumentParams::Params, "textDocument/willSave");
+
+/**
+ * The document will save request is sent from the client to the server before the document is actually saved.
+ * The request can return an array of TextEdits which will be applied to the text document before it is saved.
+ * Please note that clients might drop results if computing the text edits took too long or if a server constantly fails on this request.
+ * This is done to keep the save fast and reliable.
+ *
+ * Registration Options: TextDocumentRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(td_willSaveWaitUntil,
+ WillSaveTextDocumentParams::Params, std::vector<lsTextEdit>, "textDocument/willSaveWaitUntil");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/utils.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/utils.cpp
new file mode 100644
index 0000000000..532f4bf6d7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/utils.cpp
@@ -0,0 +1,602 @@
+#include "utils.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstring>
+#include <fstream>
+#include <functional>
+
+#include <queue>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <sys/stat.h>
+
+#include "lsPosition.h"
+#include "utf8.h"
+#ifdef _WIN32
+#include <Windows.h>
+#endif
+
+
+// DEFAULT_RESOURCE_DIRECTORY is passed with quotes for non-MSVC compilers, ie,
+// foo vs "foo".
+#if defined(_MSC_VER)
+#define _STRINGIFY(x) #x
+#define ENSURE_STRING_MACRO_ARGUMENT(x) _STRINGIFY(x)
+#else
+#define ENSURE_STRING_MACRO_ARGUMENT(x) x
+#endif
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/algorithm/string.hpp>
+namespace lsp
+{
+
+
+// See http://stackoverflow.com/a/2072890
+bool EndsWith(std::string value, std::string ending) {
+ if (ending.size() > value.size())
+ return false;
+ return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+}
+
+bool StartsWith(std::string value, std::string start) {
+ if (start.size() > value.size())
+ return false;
+ return std::equal(start.begin(), start.end(), value.begin());
+}
+
+bool AnyStartsWith(const std::vector<std::string>& values,
+ const std::string& start) {
+ return std::any_of(
+ std::begin(values), std::end(values),
+ [&start](const std::string& value) { return StartsWith(value, start); });
+}
+
+bool StartsWithAny(const std::string& value,
+ const std::vector<std::string>& startings) {
+ return std::any_of(std::begin(startings), std::end(startings),
+ [&value](const std::string& starting) {
+ return StartsWith(value, starting);
+ });
+}
+
+bool EndsWithAny(const std::string& value,
+ const std::vector<std::string>& endings) {
+ return std::any_of(
+ std::begin(endings), std::end(endings),
+ [&value](const std::string& ending) { return EndsWith(value, ending); });
+}
+
+bool FindAnyPartial(const std::string& value,
+ const std::vector<std::string>& values) {
+ return std::any_of(std::begin(values), std::end(values),
+ [&value](const std::string& v) {
+ return value.find(v) != std::string::npos;
+ });
+}
+
+std::string GetDirName(std::string path) {
+
+ ReplaceAll(path, "\\", "/");
+ if (path.size() && path.back() == '/')
+ path.pop_back();
+ size_t last_slash = path.find_last_of('/');
+ if (last_slash == std::string::npos)
+ return "./";
+ return path.substr(0, last_slash + 1);
+}
+
+std::string GetBaseName(const std::string& path) {
+ size_t last_slash = path.find_last_of('/');
+ if (last_slash != std::string::npos && (last_slash + 1) < path.size())
+ return path.substr(last_slash + 1);
+ return path;
+}
+
+std::string StripFileType(const std::string& path) {
+ size_t last_period = path.find_last_of('.');
+ if (last_period != std::string::npos)
+ return path.substr(0, last_period);
+ return path;
+}
+
+// See http://stackoverflow.com/a/29752943
+std::string ReplaceAll(const std::string& source,
+ const std::string& from,
+ const std::string& to) {
+ std::string result;
+ result.reserve(source.length()); // avoids a few memory allocations
+
+ std::string::size_type last_pos = 0;
+ std::string::size_type find_pos;
+
+ while (std::string::npos != (find_pos = source.find(from, last_pos))) {
+ result.append(source, last_pos, find_pos - last_pos);
+ result += to;
+ last_pos = find_pos + from.length();
+ }
+
+ // Care for the rest after last occurrence
+ result += source.substr(last_pos);
+
+ return result;
+}
+
+std::vector<std::string> SplitString(const std::string& str,
+ const std::string& delimiter) {
+ // http://stackoverflow.com/a/13172514
+ std::vector<std::string> strings;
+
+ std::string::size_type pos = 0;
+ std::string::size_type prev = 0;
+ while ((pos = str.find(delimiter, prev)) != std::string::npos) {
+ strings.emplace_back(str.substr(prev, pos - prev));
+ prev = pos + 1;
+ }
+
+ // To get the last substring (or only, if delimiter is not found)
+ strings.emplace_back(str.substr(prev));
+
+ return strings;
+}
+
+void EnsureEndsInSlash(std::string& path) {
+ if (path.empty() || path[path.size() - 1] != '/')
+ path += '/';
+}
+
+std::string EscapeFileName(std::string path) {
+ if (path.size() && path.back() == '/')
+ path.pop_back();
+ std::replace(path.begin(), path.end(), '\\', '@');
+ std::replace(path.begin(), path.end(), '/', '@');
+ std::replace(path.begin(), path.end(), ':', '@');
+ return path;
+}
+
+// http://stackoverflow.com/a/6089413
+std::istream& SafeGetline(std::istream& is, std::string& t) {
+ t.clear();
+
+ // The characters in the stream are read one-by-one using a std::streambuf.
+ // That is faster than reading them one-by-one using the std::istream. Code
+ // that uses streambuf this way must be guarded by a sentry object. The sentry
+ // object performs various tasks, such as thread synchronization and updating
+ // the stream state.
+
+ std::istream::sentry se(is, true);
+ std::streambuf* sb = is.rdbuf();
+
+ for (;;) {
+ int c = sb->sbumpc();
+ if (c == EOF) {
+ // Also handle the case when the last line has no line ending
+ if (t.empty())
+ is.setstate(std::ios::eofbit);
+ return is;
+ }
+
+ t += (char)c;
+
+ if (c == '\n')
+ return is;
+ }
+}
+
+bool FileExists(const std::string& filename) {
+ std::ifstream cache(filename);
+ return cache.is_open();
+}
+
+boost::optional<std::string> ReadContent(const AbsolutePath& filename) {
+
+ std::ifstream cache;
+ cache.open(filename.path);
+
+ try {
+ return std::string(std::istreambuf_iterator<char>(cache),
+ std::istreambuf_iterator<char>());
+ } catch (std::ios_base::failure&) {
+ return {};
+ }
+}
+
+std::vector<std::string> ReadLinesWithEnding(const AbsolutePath& filename) {
+ std::vector<std::string> result;
+
+ std::ifstream input(filename.path);
+ for (std::string line; SafeGetline(input, line);)
+ result.emplace_back(line);
+
+ return result;
+}
+
+bool WriteToFile(const std::string& filename, const std::string& content) {
+ std::ofstream file(filename,
+ std::ios::out | std::ios::trunc | std::ios::binary);
+ if (!file.good()) {
+
+ return false;
+ }
+
+ file << content;
+ return true;
+}
+
+
+std::string FormatMicroseconds(long long microseconds) {
+ long long milliseconds = microseconds / 1000;
+ long long remaining = microseconds - milliseconds;
+
+ // Only show two digits after the dot.
+ while (remaining >= 100)
+ remaining /= 10;
+
+ return std::to_string(milliseconds) + "." + std::to_string(remaining) + "ms";
+}
+
+
+
+std::string UpdateToRnNewlines(std::string output) {
+ size_t idx = 0;
+ while (true) {
+ idx = output.find('\n', idx);
+
+ // No more matches.
+ if (idx == std::string::npos)
+ break;
+
+ // Skip an existing "\r\n" match.
+ if (idx > 0 && output[idx - 1] == '\r') {
+ ++idx;
+ continue;
+ }
+
+ // Replace "\n" with "\r|n".
+ output.replace(output.begin() + idx, output.begin() + idx + 1, "\r\n");
+ }
+
+ return output;
+}
+
+
+
+bool IsAbsolutePath(const std::string& path) {
+ return IsUnixAbsolutePath(path) || IsWindowsAbsolutePath(path);
+}
+
+bool IsUnixAbsolutePath(const std::string& path) {
+ return !path.empty() && path[0] == '/';
+}
+
+bool IsWindowsAbsolutePath(const std::string& path) {
+ auto is_drive_letter = [](char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+ };
+
+ return path.size() > 3 && path[1] == ':' &&
+ (path[2] == '/' || path[2] == '\\') && is_drive_letter(path[0]);
+}
+
+bool IsDirectory(const std::string& path) {
+ struct stat path_stat;
+
+ if (stat(path.c_str(), &path_stat) != 0) {
+ perror("cannot access path");
+ return false;
+ }
+
+ return path_stat.st_mode & S_IFDIR;
+}
+
+
+std::string ws2s(std::wstring const& wstr) {
+
+ std::string narrow;
+ utf8::utf32to8(wstr.begin(), wstr.end(), std::back_inserter(narrow));
+ return narrow;
+}
+std::wstring s2ws(const std::string& str) {
+ std::wstring wide;
+ utf8::utf8to32(str.begin(), str.end(), std::back_inserter(wide));
+ return wide;
+}
+
+
+#ifdef _WIN32
+
+#else
+// Returns the canonicalized absolute pathname, without expanding symbolic
+// links. This is a variant of realpath(2), C++ rewrite of
+// https://github.com/freebsd/freebsd/blob/master/lib/libc/stdlib/realpath.c
+AbsolutePath RealPathNotExpandSymlink(std::string path,
+ bool ensure_exists) {
+ if (path.empty()) {
+ errno = EINVAL;
+ return {};
+ }
+ if (path[0] == '\0') {
+ errno = ENOENT;
+ return {};
+ }
+
+ // Do not use PATH_MAX because it is tricky on Linux.
+ // See https://eklitzke.org/path-max-is-tricky
+ char tmp[1024];
+ std::string resolved;
+ size_t i = 0;
+ struct stat sb;
+ if (path[0] == '/') {
+ resolved = "/";
+ i = 1;
+ }
+ else {
+ if (!getcwd(tmp, sizeof tmp) && ensure_exists)
+ return {};
+ resolved = tmp;
+ }
+
+ while (i < path.size()) {
+ auto j = path.find('/', i);
+ if (j == std::string::npos)
+ j = path.size();
+ auto next_token = path.substr(i, j - i);
+ i = j + 1;
+ if (resolved.back() != '/')
+ resolved += '/';
+ if (next_token.empty() || next_token == ".") {
+ // Handle consequential slashes and "."
+ continue;
+ }
+ else if (next_token == "..") {
+ // Strip the last path component except when it is single "/"
+ if (resolved.size() > 1)
+ resolved.resize(resolved.rfind('/', resolved.size() - 2) + 1);
+ continue;
+ }
+ // Append the next path component.
+ // Here we differ from realpath(3), we use stat(2) instead of
+ // lstat(2) because we do not want to resolve symlinks.
+ resolved += next_token;
+ if (stat(resolved.c_str(), &sb) != 0 && ensure_exists)
+ return {};
+ if (!S_ISDIR(sb.st_mode) && j < path.size() && ensure_exists) {
+ errno = ENOTDIR;
+ return {};
+ }
+ }
+
+ // Remove trailing slash except when a single "/".
+ if (resolved.size() > 1 && resolved.back() == '/')
+ resolved.pop_back();
+ return AbsolutePath(resolved, true /*validate*/);
+}
+#endif
+
+
+AbsolutePath NormalizePath(const std::string& path0,
+ bool ensure_exists ,
+ bool force_lower_on_windows) {
+#ifdef _WIN32
+
+ std::wstring path = lsp::s2ws(path0);
+
+ wchar_t buffer[MAX_PATH] = (L"");
+
+ // Normalize the path name, ie, resolve `..`.
+ unsigned long len = GetFullPathNameW(path.c_str(), MAX_PATH, buffer, nullptr);
+ if (!len)
+ return {};
+ path = std::wstring(buffer, len);
+
+ // Get the actual casing of the path, ie, if the file on disk is `C:\FooBar`
+ // and this function is called with `c:\fooBar` this will return `c:\FooBar`.
+ // (drive casing is lowercase).
+ if (ensure_exists) {
+ len = GetLongPathNameW(path.c_str(), buffer, MAX_PATH);
+ if (!len)
+ return {};
+ path = std::wstring(buffer, len);
+ }
+
+ // Empty paths have no meaning.
+ if (path.empty())
+ return {};
+
+ // We may need to normalize the drive name to upper-case; at the moment
+ // vscode sends lower-case path names.
+ /*
+ path[0] = toupper(path[0]);
+ */
+ // Make the path all lower-case, since windows is case-insensitive.
+ if (force_lower_on_windows) {
+ for (size_t i = 0; i < path.size(); ++i)
+ path[i] = (wchar_t)tolower(path[i]);
+ }
+
+ // cquery assumes forward-slashes.
+ std::replace(path.begin(), path.end(), '\\', '/');
+
+
+ return AbsolutePath(lsp::ws2s(path), false /*validate*/);
+#else
+
+ return RealPathNotExpandSymlink(path0, ensure_exists);
+
+#endif
+
+
+}
+
+// VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent
+// text documents.
+// We use a UTF-8 iterator to approximate UTF-16 in the specification (weird).
+// This is good enough and fails only for UTF-16 surrogate pairs.
+int GetOffsetForPosition(lsPosition position, const std::string& content) {
+ size_t i = 0;
+ // Iterate lines until we have found the correct line.
+ while (position.line > 0 && i < content.size()) {
+ if (content[i] == '\n')
+ position.line--;
+ i++;
+ }
+ // Iterate characters on the target line.
+ while (position.character > 0 && i < content.size()) {
+ if (uint8_t(content[i++]) >= 128) {
+ // Skip 0b10xxxxxx
+ while (i < content.size() && uint8_t(content[i]) >= 128 &&
+ uint8_t(content[i]) < 192)
+ i++;
+ }
+ position.character--;
+ }
+ return int(i);
+}
+
+
+lsPosition GetPositionForOffset(size_t offset,const std::string& content) {
+ lsPosition result;
+ for (size_t i = 0; i < offset && i < content.length(); ++i) {
+ if (content[i] == '\n') {
+ result.line++;
+ result.character = 0;
+ }
+ else {
+ result.character++;
+ }
+ }
+ return result;
+}
+
+lsPosition CharPos(const std::string& search,
+ char character,
+ int character_offset) {
+ lsPosition result;
+ size_t index = 0;
+ while (index < search.size()) {
+ char c = search[index];
+ if (c == character)
+ break;
+ if (c == '\n') {
+ result.line += 1;
+ result.character = 0;
+ }
+ else {
+ result.character += 1;
+ }
+ ++index;
+ }
+ assert(index < search.size());
+ result.character += character_offset;
+ return result;
+}
+
+void scanDirsUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret)
+{
+ namespace fs = boost::filesystem;
+ fs::path fullpath(rootPath);
+ if (!fs::exists(fullpath)) { return; }
+ fs::recursive_directory_iterator end_iter;
+ for (fs::recursive_directory_iterator iter(fullpath); iter != end_iter; iter++) {
+ try {
+ if (fs::is_directory(*iter)) {
+ ret.push_back(iter->path().wstring());
+ }
+ }
+ catch (const std::exception& ex) {
+ continue;
+ }
+ }
+}
+
+void scanDirsNoRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret)
+{
+ namespace fs = boost::filesystem;
+ boost::filesystem::path myPath(rootPath);
+ if (!fs::exists(rootPath)) { return; }
+ boost::filesystem::directory_iterator endIter;
+ for (boost::filesystem::directory_iterator iter(myPath); iter != endIter; iter++) {
+ if (boost::filesystem::is_directory(*iter)) {
+ ret.push_back(iter->path().wstring());
+ }
+ }
+}
+
+void scanFilesUseRecursive(
+ const std::wstring& rootPath,
+ std::vector<std::wstring>& ret,
+ std::wstring suf) {
+ namespace fs = boost::filesystem;
+ boost::to_lower(suf);
+
+ fs::path fullpath(rootPath);
+ if (!fs::exists(fullpath)) { return; }
+ fs::recursive_directory_iterator end_iter;
+ for (fs::recursive_directory_iterator iter(fullpath); iter != end_iter; iter++) {
+ try {
+ if (!fs::is_directory(*iter) && fs::is_regular_file(*iter)) {
+ auto temp_path = iter->path().wstring();
+ auto size = suf.size();
+ if (!size)
+ {
+ ret.push_back(std::move(temp_path));
+ }
+ else
+ {
+
+ if (temp_path.size() < size) continue;
+ auto suf_temp = temp_path.substr(temp_path.size() - size);
+ boost::to_lower(suf_temp);
+ if (suf_temp == suf)
+ {
+ ret.push_back(std::move(temp_path));
+ }
+ }
+ }
+ }
+ catch (const std::exception&) {
+ continue;
+ }
+ }
+}
+
+void scanFileNamesUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret,
+ std::wstring strSuf)
+{
+ scanFilesUseRecursive(rootPath, ret, strSuf);
+ std::vector<std::wstring> names;
+ for (auto& it : ret)
+ {
+ if (it.size() >= rootPath.size())
+ {
+ names.push_back(it.substr(rootPath.size()));
+ }
+ }
+ ret.swap(names);
+}
+
+void scanFileNamesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret, std::string strSuf)
+{
+ std::vector<std::wstring> out;
+ scanFileNamesUseRecursive(s2ws(rootPath), out, s2ws(strSuf));
+ for (auto& it : out)
+ {
+ ret.push_back(ws2s(it));
+ }
+}
+
+void scanFilesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret, std::string strSuf)
+{
+ std::vector<std::wstring> out;
+ scanFilesUseRecursive(s2ws(rootPath), out, s2ws(strSuf));
+ for (auto& it : out)
+ {
+ ret.push_back(ws2s(it));
+ }
+}
+
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/utils.h b/graphics/asymptote/LspCpp/LibLsp/lsp/utils.h
new file mode 100644
index 0000000000..796b5d2569
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/utils.h
@@ -0,0 +1,141 @@
+#pragma once
+#include <algorithm>
+#include <codecvt>
+#include <functional>
+#include <iterator>
+#include <locale>
+#include <memory>
+#include <string>
+#include <vector>
+#include <boost/optional/optional.hpp>
+#include <LibLsp/lsp/AbsolutePath.h>
+
+#include "lsPosition.h"
+
+
+namespace lsp
+{
+
+
+// Returns true if |value| starts/ends with |start| or |ending|.
+bool StartsWith(std::string value, std::string start);
+bool EndsWith(std::string value, std::string ending);
+bool AnyStartsWith(const std::vector<std::string>& values,
+ const std::string& start);
+bool StartsWithAny(const std::string& value,
+ const std::vector<std::string>& startings);
+bool EndsWithAny(const std::string& value,
+ const std::vector<std::string>& endings);
+bool FindAnyPartial(const std::string& value,
+ const std::vector<std::string>& values);
+// Returns the dirname of |path|, i.e. "foo/bar.cc" => "foo/", "foo" => "./",
+// "/foo" => "/". The result always ends in '/'.
+std::string GetDirName(std::string path);
+// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc".
+std::string GetBaseName(const std::string& path);
+// Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar".
+std::string StripFileType(const std::string& path);
+
+std::string ReplaceAll(const std::string& source,
+ const std::string& from,
+ const std::string& to);
+
+std::vector<std::string> SplitString(const std::string& str,
+ const std::string& delimiter);
+
+template <typename TValues, typename TMap>
+std::string StringJoinMap(const TValues& values,
+ const TMap& map,
+ const std::string& sep = ", ") {
+ std::string result;
+ bool first = true;
+ for (auto& entry : values) {
+ if (!first)
+ result += sep;
+ first = false;
+ result += map(entry);
+ }
+ return result;
+}
+
+template <typename TValues>
+std::string StringJoin(const TValues& values, const std::string& sep = ", ") {
+ return StringJoinMap(values, [](const std::string& entry) { return entry; },
+ sep);
+}
+
+template <typename TCollection, typename TValue>
+bool ContainsValue(const TCollection& collection, const TValue& value) {
+ return std::find(std::begin(collection), std::end(collection), value) !=
+ std::end(collection);
+}
+
+
+// Ensures that |path| ends in a slash.
+void EnsureEndsInSlash(std::string& path);
+
+// Converts a file path to one that can be used as filename.
+// e.g. foo/bar.c => foo_bar.c
+std::string EscapeFileName(std::string path);
+
+// FIXME: Move ReadContent into ICacheManager?
+bool FileExists(const std::string& filename);
+boost::optional<std::string> ReadContent(const AbsolutePath& filename);
+std::vector<std::string> ReadLinesWithEnding(const AbsolutePath& filename);
+
+bool WriteToFile(const std::string& filename, const std::string& content);
+
+
+template <typename T, typename Fn>
+void RemoveIf(std::vector<T>* vec, Fn predicate) {
+ vec->erase(std::remove_if(vec->begin(), vec->end(), predicate), vec->end());
+}
+
+std::string FormatMicroseconds(long long microseconds);
+
+// Makes sure all newlines in |output| are in \r\n format.
+std::string UpdateToRnNewlines(std::string output);
+
+// Utility methods to check if |path| is absolute.
+bool IsAbsolutePath(const std::string& path);
+bool IsUnixAbsolutePath(const std::string& path);
+bool IsWindowsAbsolutePath(const std::string& path);
+
+bool IsDirectory(const std::string& path);
+
+// string <-> wstring conversion (UTF-16), e.g. for use with Window's wide APIs.
+ std::string ws2s(std::wstring const& wstr);
+ std::wstring s2ws(std::string const& str);
+
+AbsolutePath NormalizePath(const std::string& path,
+ bool ensure_exists = true,
+ bool force_lower_on_windows = true);
+
+
+int GetOffsetForPosition(lsPosition position, const std::string& content);
+
+// Finds the position for an |offset| in |content|.
+lsPosition GetPositionForOffset(int offset, const std::string& content);
+
+// Utility method to find a position for the given character.
+lsPosition CharPos(const std::string& search,
+ char character,
+ int character_offset = 0);
+
+
+ void scanDirsNoRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret);
+
+ void scanFilesUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret,
+ std::wstring strSuf = L"");
+
+ void scanFileNamesUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret,
+ std::wstring strSuf = L"");
+ void scanFileNamesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret,
+ std::string strSuf = "");
+
+ void scanFilesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret,
+ std::string strSuf = "");
+
+ void scanDirsUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret);
+
+}
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/windows/MessageNotify.h b/graphics/asymptote/LspCpp/LibLsp/lsp/windows/MessageNotify.h
new file mode 100644
index 0000000000..8499304f55
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/windows/MessageNotify.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+// Show a message to the user.
+enum class lsMessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 };
+MAKE_REFLECT_TYPE_PROXY(lsMessageType)
+struct MessageParams {
+/**
+ * The message type.
+ */
+
+ lsMessageType type = lsMessageType::Error;
+
+/**
+ * The actual message.
+ */
+ std::string message;
+
+ void swap(MessageParams& arg) noexcept {
+ lsMessageType temp = type;
+ type = arg.type;
+ arg.type = temp;
+ message.swap(arg.message);
+ }
+};
+MAKE_REFLECT_STRUCT(MessageParams, type, message)
+
+ /**
+ * The log message notification is send from the server to the client to ask
+ * the client to log a particular message.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_LogMessage, MessageParams, "window/logMessage")
+
+
+/**
+ * The show message notification is sent from a server to a client to ask
+ * the client to display a particular message in the user interface.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_ShowMessage, MessageParams, "window/showMessage")
+
+
+
+/**
+ * The show message request is sent from a server to a client to ask the client to display a particular message in the
+ * user class. In addition to the show message notification the request allows to pass actions and to wait for an
+ * answer from the client.
+ */
+struct MessageActionItem {
+ /**
+ * A short title like 'Retry', 'Open Log' etc.
+ */
+
+ std::string title;
+ MAKE_SWAP_METHOD(MessageActionItem, title)
+};
+MAKE_REFLECT_STRUCT(MessageActionItem, title);
+
+
+struct ShowMessageRequestParams :public MessageParams {
+ /**
+ * The message action items to present.
+ */
+ std::vector<MessageActionItem> actions;
+
+ MAKE_SWAP_METHOD(ShowMessageRequestParams, type, message, actions)
+
+};
+MAKE_REFLECT_STRUCT(ShowMessageRequestParams, type, message, actions)
+
+/**
+* The show message request is sent from a server to a client to ask the
+* client to display a particular message in the user interface. In addition
+* to the show message notification the request allows to pass actions and
+* to wait for an answer from the client.
+*/
+
+DEFINE_REQUEST_RESPONSE_TYPE(WindowShowMessage, ShowMessageRequestParams, MessageActionItem, "window/showMessage")
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/working_files.cpp b/graphics/asymptote/LspCpp/LibLsp/lsp/working_files.cpp
new file mode 100644
index 0000000000..370a038274
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/working_files.cpp
@@ -0,0 +1,186 @@
+#include "working_files.h"
+#include <algorithm>
+#include <climits>
+#include <numeric>
+#include "utils.h"
+#include <memory>
+#include "LibLsp/lsp/AbsolutePath.h"
+using namespace lsp;
+struct WorkingFilesData
+{
+ std::map<AbsolutePath, std::shared_ptr<WorkingFile> > files;
+ std::mutex files_mutex; // Protects |d_ptr->files|.
+};
+
+WorkingFile::WorkingFile(WorkingFiles& _parent, const AbsolutePath& filename,
+ const std::string& buffer_content)
+ : filename(filename), directory(filename), parent(_parent), counter(0), buffer_content(buffer_content)
+{
+ directory = Directory(GetDirName(filename.path));
+}
+
+WorkingFile::WorkingFile(WorkingFiles& _parent, const AbsolutePath& filename,
+ std::string&& buffer_content)
+ : filename(filename), directory(filename), parent(_parent), counter(0), buffer_content(buffer_content)
+{
+ directory = Directory(GetDirName(filename.path));
+}
+
+WorkingFiles::WorkingFiles():d_ptr(new WorkingFilesData())
+{
+}
+
+WorkingFiles::~WorkingFiles()
+{
+ delete d_ptr;
+
+}
+
+
+
+void WorkingFiles::CloseFilesInDirectory(const std::vector<Directory>& directories)
+{
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+ std::vector<AbsolutePath> files_to_be_delete;
+
+ for(auto& it : d_ptr->files)
+ {
+ for (auto& dir : directories)
+ {
+ if (it.second->directory == dir) {
+ files_to_be_delete.emplace_back(it.first);
+ }
+ }
+ }
+
+ for(auto& it : files_to_be_delete)
+ {
+ d_ptr->files.erase(it);
+ }
+}
+
+
+
+
+std::shared_ptr<WorkingFile> WorkingFiles::GetFileByFilename(const AbsolutePath& filename) {
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+ return GetFileByFilenameNoLock(filename);
+}
+
+std::shared_ptr<WorkingFile> WorkingFiles::GetFileByFilenameNoLock(
+ const AbsolutePath& filename) {
+ const auto findIt = d_ptr->files.find(filename);
+ if ( findIt != d_ptr->files.end())
+ {
+ return findIt->second;
+ }
+ return nullptr;
+}
+
+
+
+std::shared_ptr<WorkingFile> WorkingFiles::OnOpen( lsTextDocumentItem& open) {
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+
+ AbsolutePath filename = open.uri.GetAbsolutePath();
+
+ // The file may already be open.
+ if (auto file = GetFileByFilenameNoLock(filename)) {
+ file->version = open.version;
+ file->buffer_content.swap(open.text);
+
+ return file;
+ }
+
+ const auto& it = d_ptr->files.insert({ filename,std::make_shared<WorkingFile>(*this,filename, std::move(open.text)) });
+ return it.first->second;
+}
+
+
+std::shared_ptr<WorkingFile> WorkingFiles::OnChange(const lsTextDocumentDidChangeParams& change) {
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+
+ AbsolutePath filename = change.textDocument.uri.GetAbsolutePath();
+ auto file = GetFileByFilenameNoLock(filename);
+ if (!file) {
+ return {};
+ }
+
+ if (change.textDocument.version)
+ file->version = *change.textDocument.version;
+ file->counter.fetch_add(1, std::memory_order_relaxed);
+ for (const lsTextDocumentContentChangeEvent& diff : change.contentChanges) {
+ // Per the spec replace everything if the rangeLength and range are not set.
+ // See https://github.com/Microsoft/language-server-protocol/issues/9.
+ if (!diff.range) {
+ file->buffer_content = diff.text;
+
+ } else {
+ int start_offset =
+ GetOffsetForPosition(diff.range->start, file->buffer_content);
+ // Ignore TextDocumentContentChangeEvent.rangeLength which causes trouble
+ // when UTF-16 surrogate pairs are used.
+ int end_offset =
+ GetOffsetForPosition(diff.range->end, file->buffer_content);
+ file->buffer_content.replace(file->buffer_content.begin() + start_offset,
+ file->buffer_content.begin() + end_offset,
+ diff.text);
+
+ }
+ }
+ return file;
+}
+
+bool WorkingFiles::OnClose(const lsTextDocumentIdentifier& close) {
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+
+ AbsolutePath filename = close.uri.GetAbsolutePath();
+ const auto findIt = d_ptr->files.find(filename);
+ if( findIt != d_ptr->files.end())
+ {
+ d_ptr->files.erase(findIt);
+ return true;
+ }
+ return false;
+}
+
+std::shared_ptr<WorkingFile> WorkingFiles::OnSave(const lsTextDocumentIdentifier& _save)
+{
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+
+ AbsolutePath filename = _save.uri.GetAbsolutePath();
+ const auto findIt = d_ptr->files.find(filename);
+ if (findIt != d_ptr->files.end())
+ {
+ std::shared_ptr<WorkingFile>& file = findIt->second;
+ lsp::WriteToFile(file->filename, file->GetContentNoLock());
+ return findIt->second;
+ }
+ return {};
+
+}
+
+bool WorkingFiles::GetFileBufferContent(std::shared_ptr<WorkingFile>&file, std::string& out)
+{
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+ if (file)
+ {
+ out = file->buffer_content;
+ return true;
+ }
+ return false;
+}
+bool WorkingFiles::GetFileBufferContent(std::shared_ptr<WorkingFile>& file, std::wstring& out)
+{
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+ if (file)
+ {
+ out = lsp::s2ws(file->buffer_content);
+ return true;
+ }
+ return false;
+}
+void WorkingFiles::Clear() {
+ std::lock_guard<std::mutex> lock(d_ptr->files_mutex);
+ d_ptr->files.clear();
+} \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/working_files.h b/graphics/asymptote/LspCpp/LibLsp/lsp/working_files.h
new file mode 100644
index 0000000000..e305fee8d0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/working_files.h
@@ -0,0 +1,72 @@
+#pragma once
+
+#include "LibLsp/lsp/lsp_diagnostic.h"
+#include "LibLsp/lsp/AbsolutePath.h"
+#include "LibLsp/lsp/textDocument/did_change.h"
+#include "LibLsp/lsp/textDocument/did_close.h"
+#include "LibLsp/lsp/textDocument/did_open.h"
+#include <mutex>
+#include <string>
+#include <memory>
+#include "Directory.h"
+
+struct WorkingFiles;
+struct WorkingFilesData;
+struct WorkingFile {
+
+ int version = 0;
+ AbsolutePath filename;
+ Directory directory;
+ WorkingFiles& parent;
+ std::atomic<long long> counter;
+ WorkingFile(WorkingFiles& ,const AbsolutePath& filename, const std::string& buffer_content);
+ WorkingFile(WorkingFiles&, const AbsolutePath& filename, std::string&& buffer_content);
+ const std::string& GetContentNoLock() const
+ {
+ return buffer_content;
+ }
+protected:
+ friend struct WorkingFiles;
+ std::string buffer_content;
+};
+
+struct WorkingFiles {
+
+ WorkingFiles();
+ ~WorkingFiles();
+
+ void CloseFilesInDirectory(const std::vector<Directory>&);
+ std::shared_ptr<WorkingFile> OnOpen(lsTextDocumentItem& open);
+ std::shared_ptr<WorkingFile> OnChange(const lsTextDocumentDidChangeParams& change);
+ bool OnClose(const lsTextDocumentIdentifier& close);
+ std::shared_ptr<WorkingFile> OnSave(const lsTextDocumentIdentifier& _save);
+
+ bool GetFileBufferContent(const AbsolutePath& filename, std::wstring& out)
+ {
+ auto file = GetFileByFilename(filename);
+ if(!file)
+ return false;
+ return GetFileBufferContent(file, out);
+ }
+ bool GetFileBufferContent(const AbsolutePath& filename,std::string& out)
+ {
+ auto file = GetFileByFilename(filename);
+ if (!file)
+ return false;
+ return GetFileBufferContent(file, out);
+ }
+ bool GetFileBufferContent(std::shared_ptr<WorkingFile>&, std::string& out);
+ bool GetFileBufferContent(std::shared_ptr<WorkingFile>&, std::wstring& out);
+
+
+ // Find the file with the given filename.
+ std::shared_ptr<WorkingFile> GetFileByFilename(const AbsolutePath& filename);
+
+ void Clear();
+private:
+ std::shared_ptr<WorkingFile> GetFileByFilenameNoLock(const AbsolutePath& filename);
+
+ WorkingFilesData* d_ptr;
+
+
+};
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/applyEdit.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/applyEdit.h
new file mode 100644
index 0000000000..7e2d8bee0a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/applyEdit.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsDocumentUri.h"
+#include "LibLsp/lsp/lsWorkspaceEdit.h"
+
+struct ApplyWorkspaceEditParams
+{
+ /**
+ * The edits to apply.
+ */
+
+ lsWorkspaceEdit edit;
+
+ /**
+ * An optional label of the workspace edit. This label is
+ * presented in the user interface for example on an undo
+ * stack to undo the workspace edit.
+ */
+ std::string label;
+
+ MAKE_SWAP_METHOD(ApplyWorkspaceEditParams, edit, label)
+};
+/**
+ * The workspace/applyEdit request is sent from the server to the client to modify resource on the client side.
+ */
+MAKE_REFLECT_STRUCT(ApplyWorkspaceEditParams, edit, label);
+
+
+
+struct ApplyWorkspaceEditResponse
+{
+ bool applied;
+ boost::optional<std::string> failureReason;
+ MAKE_SWAP_METHOD(ApplyWorkspaceEditResponse, applied, failureReason)
+};
+MAKE_REFLECT_STRUCT(ApplyWorkspaceEditResponse, applied, failureReason);
+
+
+DEFINE_REQUEST_RESPONSE_TYPE(WorkspaceApply, ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse, "workspace/applyEdit");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/configuration.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/configuration.h
new file mode 100644
index 0000000000..f7709aa607
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/configuration.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsDocumentUri.h"
+
+
+struct ConfigurationItem {
+ /**
+ * The scope to get the configuration section for.
+ */
+ lsDocumentUri scopeUri;
+
+ /**
+ * The configuration section asked for.
+ */
+ std::string section;
+ MAKE_SWAP_METHOD(ConfigurationItem, scopeUri, section);
+};
+MAKE_REFLECT_STRUCT(ConfigurationItem, scopeUri, section);
+struct ConfigurationParams
+{
+ std::vector<ConfigurationItem> items;
+ MAKE_SWAP_METHOD(ConfigurationParams, items)
+};
+
+MAKE_REFLECT_STRUCT(ConfigurationParams, items);
+
+/**
+ * The workspace/configuration request is sent from the server to the client to fetch
+ * configuration settings from the client. The request can fetch n configuration settings
+ * in one roundtrip. The order of the returned configuration settings correspond to the
+ * order of the passed ConfigurationItems (e.g. the first item in the response is the
+ * result for the first configuration item in the params).
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(WorkspaceConfiguration, ConfigurationParams,std::vector<lsp::Any>, "workspace/configuration"); \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h
new file mode 100644
index 0000000000..78f000f30d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h
@@ -0,0 +1,48 @@
+#pragma once
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/lsp/workspace/workspaceFolders.h"
+/**
+ * The workspace folder change event.
+ */
+struct WorkspaceFoldersChangeEvent {
+ /**
+ * The array of added workspace folders
+ */
+
+ std::vector<WorkspaceFolder> added;
+
+ /**
+ * The array of the removed workspace folders
+ */
+
+ std::vector <WorkspaceFolder> removed;
+ MAKE_SWAP_METHOD(WorkspaceFoldersChangeEvent, added, removed);
+
+};
+MAKE_REFLECT_STRUCT(WorkspaceFoldersChangeEvent, added, removed);
+
+struct DidChangeWorkspaceFoldersParams {
+ /**
+ * The actual workspace folder change event.
+ */
+
+ WorkspaceFoldersChangeEvent event;
+
+ MAKE_SWAP_METHOD(DidChangeWorkspaceFoldersParams, event);
+};
+MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParams, event);
+
+
+/**
+ * The workspace/didChangeWorkspaceFolders notification is sent from the client
+ * to the server to inform the server about workspace folder configuration changes.
+ * The notification is sent by default if both ServerCapabilities/workspaceFolders
+ * and ClientCapabilities/workspace/workspaceFolders are true; or if the server has
+ * registered to receive this notification it first.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_WorkspaceDidChangeWorkspaceFolders,
+ DidChangeWorkspaceFoldersParams, "workspace/didChangeWorkspaceFolders");
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_configuration.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_configuration.h
new file mode 100644
index 0000000000..8f8acceea4
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_configuration.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+
+#include "workspaceFolders.h"
+
+
+
+
+struct lsDidChangeConfigurationParams {
+ /**
+ * The actual changed settings.
+ */
+ lsp::Any settings;
+ MAKE_SWAP_METHOD(lsDidChangeConfigurationParams, settings);
+};
+
+MAKE_REFLECT_STRUCT(lsDidChangeConfigurationParams, settings);
+
+/**
+ * A notification sent from the client to the server to signal the change of
+ * configuration settings.
+ */
+DEFINE_NOTIFICATION_TYPE(Notify_WorkspaceDidChangeConfiguration, lsDidChangeConfigurationParams, "workspace/didChangeConfiguration");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_watched_files.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_watched_files.h
new file mode 100644
index 0000000000..c14a7e0eda
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/did_change_watched_files.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+#include "LibLsp/lsp/lsDocumentUri.h"
+enum class lsFileChangeType {
+ Created = 1,
+ Changed = 2,
+ Deleted = 3,
+};
+
+#ifdef _WIN32
+MAKE_REFLECT_TYPE_PROXY(lsFileChangeType);
+#else
+//#pragma clang diagnostic push
+//#pragma clang diagnostic ignored "-Wunused-function"
+MAKE_REFLECT_TYPE_PROXY(lsFileChangeType);
+//#pragma clang diagnostic pop
+#endif
+
+
+/**
+ * An event describing a file change.
+ */
+struct lsFileEvent {
+ lsDocumentUri uri;
+ lsFileChangeType type;
+
+ MAKE_SWAP_METHOD(lsFileEvent, uri, type)
+};
+MAKE_REFLECT_STRUCT(lsFileEvent, uri, type);
+
+struct lsDidChangeWatchedFilesParams {
+ std::vector<lsFileEvent> changes;
+ MAKE_SWAP_METHOD(lsDidChangeWatchedFilesParams, changes);
+};
+MAKE_REFLECT_STRUCT(lsDidChangeWatchedFilesParams, changes);
+
+ /**
+ * The workspace/didChangeWorkspaceFolders notification is sent from the client
+ * to the server to inform the server about workspace folder configuration changes.
+ * The notification is sent by default if both ServerCapabilities/workspaceFolders
+ * and ClientCapabilities/workspace/workspaceFolders are true; or if the server has
+ * registered to receive this notification it first.
+ */
+
+DEFINE_NOTIFICATION_TYPE(Notify_WorkspaceDidChangeWatchedFiles, lsDidChangeWatchedFilesParams, "workspace/didChangeWatchedFiles");
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/execute_command.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/execute_command.h
new file mode 100644
index 0000000000..c656ee5ef7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/execute_command.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "LibLsp/lsp/ExecuteCommandParams.h"
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/JsonRpc/NotificationInMessage.h"
+
+
+
+/**
+ * The workspace/executeCommand request is sent from the client to the
+ * server to trigger command execution on the server. In most cases the
+ * server creates a WorkspaceEdit structure and applies the changes to the
+ * workspace using the request workspace/applyEdit which is sent from the
+ * server to the client.
+ *
+ * Registration Options: ExecuteCommandRegistrationOptions
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(wp_executeCommand, ExecuteCommandParams, lsp::Any, "workspace/executeCommand");
+
+
+DEFINE_NOTIFICATION_TYPE(Notify_sendNotification, ExecuteCommandParams, "workspace/notify") \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/symbol.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/symbol.h
new file mode 100644
index 0000000000..129fb5e822
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/symbol.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "LibLsp/lsp/symbol.h"
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+/**
+ * The workspace symbol request is sent from the client to the server to
+ * list project-wide symbols matching the query string.
+ *
+ * Registration Options: void
+ */
+
+DEFINE_REQUEST_RESPONSE_TYPE(wp_symbol, WorkspaceSymbolParams, std::vector<lsSymbolInformation>, "workspace/symbol");
+
diff --git a/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/workspaceFolders.h b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/workspaceFolders.h
new file mode 100644
index 0000000000..7cedcfa5f4
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LibLsp/lsp/workspace/workspaceFolders.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "LibLsp/JsonRpc/RequestInMessage.h"
+#include "LibLsp/JsonRpc/lsResponseMessage.h"
+
+#include "LibLsp/lsp/lsDocumentUri.h"
+struct WorkspaceFolder {
+ /**
+ * The associated URI for this workspace folder.
+ */
+
+ lsDocumentUri uri;
+
+ /**
+ * The name of the workspace folder. Defaults to the uri's basename.
+ */
+ std::string name;
+
+ MAKE_SWAP_METHOD(WorkspaceFolder, uri, name)
+};
+MAKE_REFLECT_STRUCT(WorkspaceFolder, uri, name);
+
+
+/**
+ * The workspace/workspaceFolders request is sent from the server to the client
+ * to fetch the current open list of workspace folders.
+ *
+ * @return null in the response if only a single file is open in the tool,
+ * an empty array if a workspace is open but no folders are configured,
+ * the workspace folders otherwise.
+ */
+DEFINE_REQUEST_RESPONSE_TYPE(WorkspaceFolders,
+ boost::optional<JsonNull>, boost::optional<std::vector< WorkspaceFolder>>, "workspace/workspaceFolders");
+
diff --git a/graphics/asymptote/LspCpp/LspCpp.filters b/graphics/asymptote/LspCpp/LspCpp.filters
new file mode 100644
index 0000000000..795e500f14
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LspCpp.filters
@@ -0,0 +1,465 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="æºæ–‡ä»¶">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="头文件">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="资æºæ–‡ä»¶">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="JsonRpc">
+ <UniqueIdentifier>{16f3c0fa-d78b-48de-ad07-3faced48badc}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp">
+ <UniqueIdentifier>{0b7b623e-2177-4c50-9364-51bad4e3a96d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\workspace">
+ <UniqueIdentifier>{05d4a0be-21a5-4e0e-92eb-f3246dc60fb0}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\textDocument">
+ <UniqueIdentifier>{555e2484-f11d-466e-b41c-263b68eda142}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\windows">
+ <UniqueIdentifier>{80aef1a6-c03b-4b19-ac86-7ec9f89dcf34}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\general">
+ <UniqueIdentifier>{db50dfa7-d3d1-45db-9c35-6274c624de32}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\JavaExtentions">
+ <UniqueIdentifier>{3fe59184-4ce8-42c3-95f8-c4af6bfef674}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\client">
+ <UniqueIdentifier>{9f073965-fffb-414e-acc3-0b61c54a2404}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="LspCpp.cpp">
+ <Filter>æºæ–‡ä»¶</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\StreamMessageProducer.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\MessageJsonHandler.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\Endpoint.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\serializer.cc">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\message.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\threaded_queue.cc">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\RemoteEndPoint.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\AbsolutePath.cc">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\lsp.cc">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\lsp_diagnostic.cc">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\method_type.cc">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\ProtocolJsonHandler.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\utils.cc">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\general\initialize.cpp">
+ <Filter>lsp\general</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\textDocument\textDocument.cpp">
+ <Filter>lsp\textDocument</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="LibLsp\JsonRpc\MessageIssue.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\MessageProducer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\StreamMessageProducer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\MessageJsonHandler.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\Endpoint.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\maybe.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\serializer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\child_process_service.hpp">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\threaded_queue.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\RemoteEndPoint.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\cancellation.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\message.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\AbsolutePath.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\config.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\hash_utils.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\location_type.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lru_cache.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsCommand.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsDocumentUri.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsFormattingOptions.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsMarkedString.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsp_code_action.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsp_completion.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsp_diagnostic.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsPosition.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsRange.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsResponseError.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentEdit.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentIdentifier.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentItem.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentPositionParams.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextEdit.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsVersionedTextDocumentIdentifier.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsWorkspaceEdit.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\method_type.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\out_list.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ProtocolJsonHandler.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ProtocolLocalEndPoint.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\symbol.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\utils.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\exit.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\initialize.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\initialized.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\shutdown.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\callHierarchy.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\code_action.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\code_lens.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\completion.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_change.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_close.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_open.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_save.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\document_link.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\document_symbol.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\formatting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\highlight.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\hover.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\implementation.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\range_formatting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\references.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\rename.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\signature_help.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\type_definition.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\typeHierarchy.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\did_change_configuration.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\did_change_watched_files.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\execute_command.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\symbol.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ResourceOperation.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsCodeAction.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\WorkspaceSymbolParams.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\searchSymbols.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\getRefactorEdit.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\buildWorkspace.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\codeActionResult.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\executeCommand.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\workspaceFolders.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\applyEdit.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\configuration.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\semanticHighlighting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\client\unregisterCapability.h">
+ <Filter>lsp\client</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\client\registerCapability.h">
+ <Filter>lsp\client</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\publishDiagnostics.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\windows\Message.h">
+ <Filter>lsp\windows</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\didChangeWorkspaceFolders.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveCompletionItem.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\declaration_definition.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsAny.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\classFileContents.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\projectConfigurationUpdate.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\listOverridableMethods.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\addOverridableMethods.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\OverridableMethod.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\checkHashCodeEqualsStatus.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\CodeActionParams.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\generateHashCodeEquals.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\organizeImports.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\checkToStringStatus.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\generateToString.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\resolveUnimplementedAccessors.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\generateAccessors.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\checkConstructorsStatus.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\generateConstructors.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\checkDelegateMethodsStatus.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\generateDelegateMethods.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\getMoveDestinations.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\Move.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\JavaExtentions\findLinks.h">
+ <Filter>lsp\JavaExtentions</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\InitializeParams.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsServerCapabilities.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsClientCapabilities.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsWorkspaceClientCapabilites.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsTextDocumentClientCapabilities.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ExecuteCommandParams.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveCodeLens.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\onTypeFormatting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\willSave.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\documentColor.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\colorPresentation.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\foldingRange.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\prepareRename.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveTypeHierarchy.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\selectionRange.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LspCpp.user b/graphics/asymptote/LspCpp/LspCpp.user
new file mode 100644
index 0000000000..88a550947e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LspCpp.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LspCpp.vcxproj b/graphics/asymptote/LspCpp/LspCpp.vcxproj
new file mode 100644
index 0000000000..e363e2a027
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LspCpp.vcxproj
@@ -0,0 +1,668 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="STDIO_CLIENT_EXAMPLE|Win32">
+ <Configuration>STDIO_CLIENT_EXAMPLE</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="STDIO_CLIENT_EXAMPLE|x64">
+ <Configuration>STDIO_CLIENT_EXAMPLE</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="STDIO_SERVER_EXAMPLE|Win32">
+ <Configuration>STDIO_SERVER_EXAMPLE</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="STDIO_SERVER_EXAMPLE|x64">
+ <Configuration>STDIO_SERVER_EXAMPLE</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="TCP_SERVER_EXAMPLE|Win32">
+ <Configuration>TCP_SERVER_EXAMPLE</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="TCP_SERVER_EXAMPLE|x64">
+ <Configuration>TCP_SERVER_EXAMPLE</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="WEBSOCKET_SERVER_EXAMPLE|Win32">
+ <Configuration>WEBSOCKET_SERVER_EXAMPLE</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="WEBSOCKET_SERVER_EXAMPLE|x64">
+ <Configuration>WEBSOCKET_SERVER_EXAMPLE</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <ProjectGuid>{F45A78DC-E57C-4AF6-8719-29833E3BFE07}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>LspCpp</RootNamespace>
+ <WindowsTargetPlatformVersion>7.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141_xp</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>.\third_party\rapidjson\include;.\third_party\utfcpp\source;.\;.\third_party\threadpool;$(IncludePath)</IncludePath>
+ <OutDir>..\Our_lib_V3</OutDir>
+ <TargetName>LspCppMDD</TargetName>
+ <TargetExt>.lib</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>.\third_party\rapidjson\include;.\third_party\utfcpp\source;.\;.\third_party\threadpool;$(IncludePath)</IncludePath>
+ <TargetName>TCP_SERVER_EXAMPLE</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>.\third_party\rapidjson\include;.\third_party\utfcpp\source;.\;.\third_party\threadpool;$(IncludePath)</IncludePath>
+ <TargetName>STDIO_SERVER_EXAMPLE</TargetName>
+ <OutDir>.\bin</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>.\third_party\rapidjson\include;.\third_party\utfcpp\source;.\;.\third_party\threadpool;$(IncludePath)</IncludePath>
+ <TargetName>STDIO_CLIENT_EXAMPLE</TargetName>
+ <OutDir>.\bin</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>.\third_party\rapidjson\include;.\third_party\utfcpp\source;.\;.\third_party\threadpool;$(IncludePath)</IncludePath>
+ <TargetName>WEBSOCKET_SERVER_EXAMPLE</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\Our_lib_V3</OutDir>
+ <TargetName>LspCppMD</TargetName>
+ <IncludePath>.\third_party\rapidjson\include;.\third_party\utfcpp\source;.\;.\third_party\threadpool;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>false</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>false</ConformanceMode>
+ <LanguageStandard>stdcpp14</LanguageStandard>
+ <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>false</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;TCP_SERVER_EXAMPLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>false</ConformanceMode>
+ <LanguageStandard>stdcpp14</LanguageStandard>
+ <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>false</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;STDIO_SERVER_EXAMPLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>false</ConformanceMode>
+ <LanguageStandard>stdcpp14</LanguageStandard>
+ <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>false</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;STDIO_CLIENT_EXAMPLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>false</ConformanceMode>
+ <LanguageStandard>stdcpp14</LanguageStandard>
+ <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>false</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;WEBSOCKET_SERVER_EXAMPLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>false</ConformanceMode>
+ <LanguageStandard>stdcpp14</LanguageStandard>
+ <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='TCP_SERVER_EXAMPLE|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_SERVER_EXAMPLE|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='STDIO_CLIENT_EXAMPLE|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='WEBSOCKET_SERVER_EXAMPLE|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>false</ConformanceMode>
+ <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
+ <LanguageStandard>stdcpp14</LanguageStandard>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="example\StdIOClientExample.cpp" />
+ <ClCompile Include="example\StdIOServerExample.cpp" />
+ <ClCompile Include="example\TcpServerExample.cpp" />
+ <ClCompile Include="example\WebsocketExample.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\Context.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\serializer.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\TcpServer.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\threaded_queue.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\WebSocketServer.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\RemoteEndPoint.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\GCThreadContext.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\Endpoint.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\message.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\MessageJsonHandler.cpp" />
+ <ClCompile Include="LibLsp\JsonRpc\StreamMessageProducer.cpp" />
+ <ClCompile Include="LibLsp\lsp\extention\sct\sct.cpp" />
+ <ClCompile Include="LibLsp\lsp\general\initialize.cpp" />
+ <ClCompile Include="LibLsp\lsp\lsp.cpp" />
+ <ClCompile Include="LibLsp\lsp\lsp_diagnostic.cpp" />
+ <ClCompile Include="LibLsp\lsp\Markup\Markup.cpp" />
+ <ClCompile Include="LibLsp\lsp\ParentProcessWatcher.cpp" />
+ <ClCompile Include="LibLsp\lsp\ProtocolJsonHandler.cpp" />
+ <ClCompile Include="LibLsp\lsp\textDocument\textDocument.cpp" />
+ <ClCompile Include="LibLsp\lsp\utils.cpp" />
+ <ClCompile Include="LibLsp\lsp\working_files.cpp" />
+ <ClCompile Include="network\uri\detail\uri_advance_parts.cpp" />
+ <ClCompile Include="network\uri\detail\uri_normalize.cpp" />
+ <ClCompile Include="network\uri\detail\uri_parse.cpp" />
+ <ClCompile Include="network\uri\detail\uri_parse_authority.cpp" />
+ <ClCompile Include="network\uri\detail\uri_resolve.cpp" />
+ <ClCompile Include="network\uri\uri.cpp" />
+ <ClCompile Include="network\uri\uri_builder.cpp" />
+ <ClCompile Include="network\uri\uri_errors.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="LibLsp\JsonRpc\Cancellation.h" />
+ <ClInclude Include="LibLsp\JsonRpc\Condition.h" />
+ <ClInclude Include="LibLsp\JsonRpc\Context.h" />
+ <ClInclude Include="LibLsp\JsonRpc\json.h" />
+ <ClInclude Include="LibLsp\JsonRpc\lsRequestId.h" />
+ <ClInclude Include="LibLsp\JsonRpc\lsResponseMessage.h" />
+ <ClInclude Include="LibLsp\JsonRpc\message.h" />
+ <ClInclude Include="LibLsp\JsonRpc\NotificationInMessage.h" />
+ <ClInclude Include="LibLsp\JsonRpc\RemoteEndPoint.h" />
+ <ClInclude Include="LibLsp\JsonRpc\GCThreadContext.h" />
+ <ClInclude Include="LibLsp\JsonRpc\Endpoint.h" />
+ <ClInclude Include="LibLsp\JsonRpc\MessageIssue.h" />
+ <ClInclude Include="LibLsp\JsonRpc\MessageJsonHandler.h" />
+ <ClInclude Include="LibLsp\JsonRpc\MessageProducer.h" />
+ <ClInclude Include="LibLsp\JsonRpc\RequestInMessage.h" />
+ <ClInclude Include="LibLsp\JsonRpc\ScopeExit.h" />
+ <ClInclude Include="LibLsp\JsonRpc\serializer.h" />
+ <ClInclude Include="LibLsp\JsonRpc\stream.h" />
+ <ClInclude Include="LibLsp\JsonRpc\StreamMessageProducer.h" />
+ <ClInclude Include="LibLsp\JsonRpc\TcpServer.h" />
+ <ClInclude Include="LibLsp\JsonRpc\threaded_queue.h" />
+ <ClInclude Include="LibLsp\JsonRpc\traits.h" />
+ <ClInclude Include="LibLsp\JsonRpc\WebSocketServer.h" />
+ <ClInclude Include="LibLsp\lsp\AbsolutePath.h" />
+ <ClInclude Include="LibLsp\lsp\ClientPreferences.h" />
+ <ClInclude Include="LibLsp\lsp\client\registerCapability.h" />
+ <ClInclude Include="LibLsp\lsp\client\unregisterCapability.h" />
+ <ClInclude Include="LibLsp\lsp\CodeActionParams.h" />
+ <ClInclude Include="LibLsp\lsp\Directory.h" />
+ <ClInclude Include="LibLsp\lsp\ExecuteCommandParams.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\addOverridableMethods.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\buildWorkspace.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkConstructorsStatus.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkDelegateMethodsStatus.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkHashCodeEqualsStatus.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkToStringStatus.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\classFileContents.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\codeActionResult.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\executeCommand.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\findLinks.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateAccessors.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateConstructors.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateDelegateMethods.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateHashCodeEquals.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateToString.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\getMoveDestinations.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\getRefactorEdit.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\listOverridableMethods.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\Move.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\organizeImports.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\OverridableMethod.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\projectConfigurationUpdate.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\resolveUnimplementedAccessors.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\searchSymbols.h" />
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\WorkspaceSymbolParams.h" />
+ <ClInclude Include="LibLsp\lsp\extention\sct\protocol.h" />
+ <ClInclude Include="LibLsp\lsp\extention\sct\sct.h" />
+ <ClInclude Include="LibLsp\lsp\extention\sct\SCTConfig.h" />
+ <ClInclude Include="LibLsp\lsp\extention\sonarlint\protocol.h" />
+ <ClInclude Include="LibLsp\lsp\general\exit.h" />
+ <ClInclude Include="LibLsp\lsp\general\initialize.h" />
+ <ClInclude Include="LibLsp\lsp\general\initialized.h" />
+ <ClInclude Include="LibLsp\lsp\general\InitializeParams.h" />
+ <ClInclude Include="LibLsp\lsp\general\lsClientCapabilities.h" />
+ <ClInclude Include="LibLsp\lsp\general\lsServerCapabilities.h" />
+ <ClInclude Include="LibLsp\lsp\general\lsTextDocumentClientCapabilities.h" />
+ <ClInclude Include="LibLsp\lsp\general\lsWorkspaceClientCapabilites.h" />
+ <ClInclude Include="LibLsp\lsp\general\progress.h" />
+ <ClInclude Include="LibLsp\lsp\general\shutdown.h" />
+ <ClInclude Include="LibLsp\lsp\IProgressMonitor.h" />
+ <ClInclude Include="LibLsp\lsp\language\language.h" />
+ <ClInclude Include="LibLsp\lsp\location_type.h" />
+ <ClInclude Include="LibLsp\lsp\lru_cache.h" />
+ <ClInclude Include="LibLsp\lsp\lsAny.h" />
+ <ClInclude Include="LibLsp\lsp\lsCodeAction.h" />
+ <ClInclude Include="LibLsp\lsp\lsCommand.h" />
+ <ClInclude Include="LibLsp\lsp\lsDocumentUri.h" />
+ <ClInclude Include="LibLsp\lsp\lsFormattingOptions.h" />
+ <ClInclude Include="LibLsp\lsp\lsMarkedString.h" />
+ <ClInclude Include="LibLsp\lsp\lsPosition.h" />
+ <ClInclude Include="LibLsp\lsp\lsp_code_action.h" />
+ <ClInclude Include="LibLsp\lsp\lsp_completion.h" />
+ <ClInclude Include="LibLsp\lsp\lsp_diagnostic.h" />
+ <ClInclude Include="LibLsp\lsp\lsRange.h" />
+ <ClInclude Include="LibLsp\lsp\lsResponseError.h" />
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentEdit.h" />
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentIdentifier.h" />
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentItem.h" />
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentPositionParams.h" />
+ <ClInclude Include="LibLsp\lsp\lsTextEdit.h" />
+ <ClInclude Include="LibLsp\lsp\lsVersionedTextDocumentIdentifier.h" />
+ <ClInclude Include="LibLsp\lsp\lsWorkspaceEdit.h" />
+ <ClInclude Include="LibLsp\lsp\Markup\Markup.h" />
+ <ClInclude Include="LibLsp\lsp\Markup\string_ref.h" />
+ <ClInclude Include="LibLsp\lsp\method_type.h" />
+ <ClInclude Include="LibLsp\lsp\out_list.h" />
+ <ClInclude Include="LibLsp\lsp\ParentProcessWatcher.h" />
+ <ClInclude Include="LibLsp\lsp\ProcessIoService.h" />
+ <ClInclude Include="LibLsp\lsp\ProtocolJsonHandler.h" />
+ <ClInclude Include="LibLsp\lsp\ResourceOperation.h" />
+ <ClInclude Include="LibLsp\lsp\SimpleTimer.h" />
+ <ClInclude Include="LibLsp\lsp\symbol.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\callHierarchy.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\code_action.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\code_lens.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\colorPresentation.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\completion.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\declaration_definition.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\didRenameFiles.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\did_change.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\did_close.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\did_open.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\did_save.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\documentColor.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\document_link.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\document_symbol.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\foldingRange.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\formatting.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\highlight.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\hover.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\implementation.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\linkedEditingRange.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\onTypeFormatting.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\prepareRename.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\publishDiagnostics.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\range_formatting.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\references.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\rename.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveCodeLens.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveCompletionItem.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveTypeHierarchy.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\selectionRange.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\semanticHighlighting.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\SemanticTokens.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\signature_help.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\typeHierarchy.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\type_definition.h" />
+ <ClInclude Include="LibLsp\lsp\textDocument\willSave.h" />
+ <ClInclude Include="LibLsp\lsp\utils.h" />
+ <ClInclude Include="LibLsp\lsp\windows\MessageNotify.h" />
+ <ClInclude Include="LibLsp\lsp\working_files.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\applyEdit.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\configuration.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\didChangeWorkspaceFolders.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\did_change_configuration.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\did_change_watched_files.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\execute_command.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\symbol.h" />
+ <ClInclude Include="LibLsp\lsp\workspace\workspaceFolders.h" />
+ <ClInclude Include="network\optional.hpp" />
+ <ClInclude Include="network\string_view.hpp" />
+ <ClInclude Include="network\uri.hpp" />
+ <ClInclude Include="network\uri\config.hpp" />
+ <ClInclude Include="network\uri\detail\algorithm.hpp" />
+ <ClInclude Include="network\uri\detail\decode.hpp" />
+ <ClInclude Include="network\uri\detail\encode.hpp" />
+ <ClInclude Include="network\uri\detail\grammar.hpp" />
+ <ClInclude Include="network\uri\detail\translate.hpp" />
+ <ClInclude Include="network\uri\detail\uri_advance_parts.hpp" />
+ <ClInclude Include="network\uri\detail\uri_normalize.hpp" />
+ <ClInclude Include="network\uri\detail\uri_parse.hpp" />
+ <ClInclude Include="network\uri\detail\uri_parse_authority.hpp" />
+ <ClInclude Include="network\uri\detail\uri_parts.hpp" />
+ <ClInclude Include="network\uri\detail\uri_percent_encode.hpp" />
+ <ClInclude Include="network\uri\detail\uri_resolve.hpp" />
+ <ClInclude Include="network\uri\uri.hpp" />
+ <ClInclude Include="network\uri\uri_builder.hpp" />
+ <ClInclude Include="network\uri\uri_errors.hpp" />
+ <ClInclude Include="network\uri\uri_io.hpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="packages\tencent.rapidjson.1.1.1\build\tencent.rapidjson.targets" Condition="Exists('packages\tencent.rapidjson.1.1.1\build\tencent.rapidjson.targets')" />
+ <Import Project="..\packages\boost.1.76.0.0\build\boost.targets" Condition="Exists('..\packages\boost.1.76.0.0\build\boost.targets')" />
+ <Import Project="..\packages\boost_chrono-vc141.1.76.0.0\build\boost_chrono-vc141.targets" Condition="Exists('..\packages\boost_chrono-vc141.1.76.0.0\build\boost_chrono-vc141.targets')" />
+ <Import Project="..\packages\boost_context-vc141.1.76.0.0\build\boost_context-vc141.targets" Condition="Exists('..\packages\boost_context-vc141.1.76.0.0\build\boost_context-vc141.targets')" />
+ <Import Project="..\packages\boost_coroutine-vc141.1.76.0.0\build\boost_coroutine-vc141.targets" Condition="Exists('..\packages\boost_coroutine-vc141.1.76.0.0\build\boost_coroutine-vc141.targets')" />
+ <Import Project="..\packages\boost_date_time-vc141.1.76.0.0\build\boost_date_time-vc141.targets" Condition="Exists('..\packages\boost_date_time-vc141.1.76.0.0\build\boost_date_time-vc141.targets')" />
+ <Import Project="..\packages\boost_filesystem-vc141.1.76.0.0\build\boost_filesystem-vc141.targets" Condition="Exists('..\packages\boost_filesystem-vc141.1.76.0.0\build\boost_filesystem-vc141.targets')" />
+ <Import Project="..\packages\boost_program_options-vc141.1.76.0.0\build\boost_program_options-vc141.targets" Condition="Exists('..\packages\boost_program_options-vc141.1.76.0.0\build\boost_program_options-vc141.targets')" />
+ <Import Project="..\packages\boost_regex-vc141.1.76.0.0\build\boost_regex-vc141.targets" Condition="Exists('..\packages\boost_regex-vc141.1.76.0.0\build\boost_regex-vc141.targets')" />
+ <Import Project="..\packages\boost_system-vc140.1.76.0.0\build\boost_system-vc140.targets" Condition="Exists('..\packages\boost_system-vc140.1.76.0.0\build\boost_system-vc140.targets')" />
+ <Import Project="..\packages\boost_thread-vc141.1.76.0.0\build\boost_thread-vc141.targets" Condition="Exists('..\packages\boost_thread-vc141.1.76.0.0\build\boost_thread-vc141.targets')" />
+ </ImportGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>è¿™å°è®¡ç®—机上缺少此项目引用的 NuGet 程åºåŒ…。使用“NuGet 程åºåŒ…还原â€å¯ä¸‹è½½è¿™äº›ç¨‹åºåŒ…。有关更多信æ¯ï¼Œè¯·å‚è§ http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\boost.1.76.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost.1.76.0.0\build\boost.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_chrono-vc141.1.76.0.0\build\boost_chrono-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_chrono-vc141.1.76.0.0\build\boost_chrono-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_context-vc141.1.76.0.0\build\boost_context-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_context-vc141.1.76.0.0\build\boost_context-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_coroutine-vc141.1.76.0.0\build\boost_coroutine-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_coroutine-vc141.1.76.0.0\build\boost_coroutine-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_date_time-vc141.1.76.0.0\build\boost_date_time-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_date_time-vc141.1.76.0.0\build\boost_date_time-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_filesystem-vc141.1.76.0.0\build\boost_filesystem-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_filesystem-vc141.1.76.0.0\build\boost_filesystem-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_program_options-vc141.1.76.0.0\build\boost_program_options-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_program_options-vc141.1.76.0.0\build\boost_program_options-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_regex-vc141.1.76.0.0\build\boost_regex-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_regex-vc141.1.76.0.0\build\boost_regex-vc141.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_system-vc140.1.76.0.0\build\boost_system-vc140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_system-vc140.1.76.0.0\build\boost_system-vc140.targets'))" />
+ <Error Condition="!Exists('..\packages\boost_thread-vc141.1.76.0.0\build\boost_thread-vc141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_thread-vc141.1.76.0.0\build\boost_thread-vc141.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LspCpp.vcxproj.filters b/graphics/asymptote/LspCpp/LspCpp.vcxproj.filters
new file mode 100644
index 0000000000..6402988303
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LspCpp.vcxproj.filters
@@ -0,0 +1,669 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="LibLsp\JsonRpc\StreamMessageProducer.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\MessageJsonHandler.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\Endpoint.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\message.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\RemoteEndPoint.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\ProtocolJsonHandler.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\general\initialize.cpp">
+ <Filter>lsp\general</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\textDocument\textDocument.cpp">
+ <Filter>lsp\textDocument</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\detail\uri_advance_parts.cpp">
+ <Filter>network\uri\detail</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\detail\uri_normalize.cpp">
+ <Filter>network\uri\detail</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\detail\uri_parse.cpp">
+ <Filter>network\uri\detail</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\detail\uri_parse_authority.cpp">
+ <Filter>network\uri\detail</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\detail\uri_resolve.cpp">
+ <Filter>network\uri\detail</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\uri.cpp">
+ <Filter>network\uri</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\uri_builder.cpp">
+ <Filter>network\uri</Filter>
+ </ClCompile>
+ <ClCompile Include="network\uri\uri_errors.cpp">
+ <Filter>network\uri</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\TcpServer.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\WebSocketServer.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="example\StdIOClientExample.cpp">
+ <Filter>example</Filter>
+ </ClCompile>
+ <ClCompile Include="example\StdIOServerExample.cpp">
+ <Filter>example</Filter>
+ </ClCompile>
+ <ClCompile Include="example\TcpServerExample.cpp">
+ <Filter>example</Filter>
+ </ClCompile>
+ <ClCompile Include="example\WebsocketExample.cpp">
+ <Filter>example</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\extention\sct\sct.cpp">
+ <Filter>lsp\extention\sct</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\serializer.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\threaded_queue.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\lsp.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\lsp_diagnostic.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\utils.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\working_files.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\ParentProcessWatcher.cpp">
+ <Filter>lsp</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\Context.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\lsp\Markup\Markup.cpp">
+ <Filter>lsp\markdown</Filter>
+ </ClCompile>
+ <ClCompile Include="LibLsp\JsonRpc\GCThreadContext.cpp">
+ <Filter>JsonRpc</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="LibLsp\JsonRpc\MessageIssue.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\MessageProducer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\StreamMessageProducer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\MessageJsonHandler.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\Endpoint.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\serializer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\RemoteEndPoint.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\Cancellation.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\message.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\location_type.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lru_cache.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsCommand.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsDocumentUri.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsFormattingOptions.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsMarkedString.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsp_code_action.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsp_completion.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsp_diagnostic.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsPosition.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsRange.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsResponseError.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentEdit.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentIdentifier.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentItem.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextDocumentPositionParams.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsTextEdit.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsVersionedTextDocumentIdentifier.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsWorkspaceEdit.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\method_type.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\out_list.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ProtocolJsonHandler.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\symbol.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\exit.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\initialize.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\initialized.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\callHierarchy.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\code_action.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\code_lens.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\completion.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_change.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_close.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_open.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\did_save.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\document_link.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\document_symbol.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\formatting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\highlight.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\hover.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\implementation.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\range_formatting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\references.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\rename.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\signature_help.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\type_definition.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\typeHierarchy.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\did_change_configuration.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\did_change_watched_files.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\execute_command.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\symbol.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ResourceOperation.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsCodeAction.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\workspaceFolders.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\applyEdit.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\configuration.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\semanticHighlighting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\publishDiagnostics.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\workspace\didChangeWorkspaceFolders.h">
+ <Filter>lsp\workspace</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveCompletionItem.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\declaration_definition.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\lsAny.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\CodeActionParams.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\InitializeParams.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsServerCapabilities.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsClientCapabilities.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsWorkspaceClientCapabilites.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\lsTextDocumentClientCapabilities.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ExecuteCommandParams.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveCodeLens.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\onTypeFormatting.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\willSave.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\documentColor.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\colorPresentation.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\foldingRange.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\prepareRename.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\resolveTypeHierarchy.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\selectionRange.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\threaded_queue.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\Condition.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\lsRequestId.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\RequestInMessage.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\NotificationInMessage.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\lsResponseMessage.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\windows\MessageNotify.h">
+ <Filter>lsp\windows</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\AbsolutePath.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\json.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\shutdown.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="network\optional.hpp">
+ <Filter>network</Filter>
+ </ClInclude>
+ <ClInclude Include="network\string_view.hpp">
+ <Filter>network</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri.hpp">
+ <Filter>network</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\algorithm.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\decode.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\encode.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\grammar.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\translate.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_advance_parts.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_normalize.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_parse.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_parse_authority.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_parts.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_percent_encode.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\detail\uri_resolve.hpp">
+ <Filter>network\uri\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\config.hpp">
+ <Filter>network\uri</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\uri.hpp">
+ <Filter>network\uri</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\uri_builder.hpp">
+ <Filter>network\uri</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\uri_errors.hpp">
+ <Filter>network\uri</Filter>
+ </ClInclude>
+ <ClInclude Include="network\uri\uri_io.hpp">
+ <Filter>network\uri</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\language\language.h">
+ <Filter>lsp\language</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\client\registerCapability.h">
+ <Filter>lsp\client</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\client\unregisterCapability.h">
+ <Filter>lsp\client</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\TcpServer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\didRenameFiles.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\stream.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\WebSocketServer.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\addOverridableMethods.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\buildWorkspace.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkConstructorsStatus.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkDelegateMethodsStatus.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkHashCodeEqualsStatus.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\checkToStringStatus.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\classFileContents.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\codeActionResult.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\executeCommand.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\findLinks.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateAccessors.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateConstructors.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateDelegateMethods.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateHashCodeEquals.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\generateToString.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\getMoveDestinations.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\getRefactorEdit.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\listOverridableMethods.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\Move.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\organizeImports.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\OverridableMethod.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\projectConfigurationUpdate.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\resolveUnimplementedAccessors.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\searchSymbols.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\jdtls\WorkspaceSymbolParams.h">
+ <Filter>lsp\extention\jdtls</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\sct\sct.h">
+ <Filter>lsp\extention\sct</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\sct\SCTConfig.h">
+ <Filter>lsp\extention\sct</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\sct\protocol.h">
+ <Filter>lsp\extention\sct</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\extention\sonarlint\protocol.h">
+ <Filter>lsp\extention\sonarlint</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\utils.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\working_files.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\Directory.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\SimpleTimer.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\general\progress.h">
+ <Filter>lsp\general</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ParentProcessWatcher.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ProcessIoService.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\Context.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\ScopeExit.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\SemanticTokens.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\textDocument\linkedEditingRange.h">
+ <Filter>lsp\textDocument</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\IProgressMonitor.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\Markup\Markup.h">
+ <Filter>lsp\markdown</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\Markup\string_ref.h">
+ <Filter>lsp\markdown</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\traits.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\JsonRpc\GCThreadContext.h">
+ <Filter>JsonRpc</Filter>
+ </ClInclude>
+ <ClInclude Include="LibLsp\lsp\ClientPreferences.h">
+ <Filter>lsp</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="JsonRpc">
+ <UniqueIdentifier>{1da4afb3-155d-423f-96b0-1b8da9acc00a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp">
+ <UniqueIdentifier>{e7d76738-44b8-4a69-a1c4-2faa28c9a4e4}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\workspace">
+ <UniqueIdentifier>{b79907e9-c622-4c4a-ba4a-856d5a924cb3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\textDocument">
+ <UniqueIdentifier>{b5ab5370-6e7b-4a19-b08a-0d60880be5c2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\windows">
+ <UniqueIdentifier>{24b7fc1b-1430-4833-afc1-7215028d56b3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\general">
+ <UniqueIdentifier>{09427494-f677-443b-b1f9-20cf6e6976f5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="network">
+ <UniqueIdentifier>{43293649-591a-46e4-ae6d-93de432e5202}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="network\uri">
+ <UniqueIdentifier>{8e1c4f26-61b7-45f3-9fca-8a709d53e924}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="network\uri\detail">
+ <UniqueIdentifier>{fca88b35-e5ec-4b6c-8e48-e7ddb54f6c5f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\language">
+ <UniqueIdentifier>{c2661f3d-8e6b-4e9c-9f8f-7b1c533198a9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\client">
+ <UniqueIdentifier>{7dc366bb-0edc-4d01-b61b-b9a25911ab44}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="example">
+ <UniqueIdentifier>{50042bb3-ac58-43e1-8cbe-0af2d1c58599}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\extention">
+ <UniqueIdentifier>{0091cb64-52d3-4c82-a25a-0a9b976182fe}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\extention\sct">
+ <UniqueIdentifier>{9a310695-9678-42c9-9085-412e178574d4}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\extention\jdtls">
+ <UniqueIdentifier>{b2e6e5b5-343f-4098-8105-4f054b3e9b38}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\extention\sonarlint">
+ <UniqueIdentifier>{11198774-b392-4339-b654-17aee0eeaa21}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="lsp\markdown">
+ <UniqueIdentifier>{4ce2a4b8-aa8d-462b-a6c9-c11b56e3bb2d}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/LspCpp.vcxproj.user b/graphics/asymptote/LspCpp/LspCpp.vcxproj.user
new file mode 100644
index 0000000000..88a550947e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/LspCpp.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/Makefile b/graphics/asymptote/LspCpp/Makefile
new file mode 100644
index 0000000000..72d5c3fedf
--- /dev/null
+++ b/graphics/asymptote/LspCpp/Makefile
@@ -0,0 +1,40 @@
+CXX=g++
+
+CFLAGS = -Wall -fPIE
+INCLUDES=-I. -ILibLsp/lsp/extention/jdtls/ -ILibLsp/JsonRpc/ -ILibLsp/JsonRpc/lsp/extention/jdtls \
+ -Ithird_party/threadpool -Ithird_party/utfcpp/source -Ithird_party/rapidjson/include
+CXXFLAGS = -std=c++14
+OPTFLAGS = -O3
+
+ALL_CXXFLAGS = $(CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(OPTFLAGS)
+
+NETWORKS_DETAIL = $(addprefix detail/, uri_advance_parts.o \
+ uri_normalize.o uri_parse.o uri_parse_authority.o uri_resolve.o)
+NETWORK_FILES = $(addprefix uri/, uri.o uri_builder.o uri_errors.o $(NETWORKS_DETAIL))
+LSP_FILES = extention/sct/sct.o general/initialize.o lsp.o lsp_diagnostic.o \
+ ProtocolJsonHandler.o textDocument/textDocument.o Markup/Markup.o ParentProcessWatcher.o \
+ utils.o working_files.o
+JSONRPC_FILES = TcpServer.o threaded_queue.o WebSocketServer.o RemoteEndPoint.o \
+ Endpoint.o message.o MessageJsonHandler.o serializer.o StreamMessageProducer.o \
+ Context.o GCThreadContext.o
+
+OFILES = $(addprefix ./network/,$(NETWORK_FILES)) \
+ $(addprefix ./LibLsp/lsp/, $(LSP_FILES)) \
+ $(addprefix ./LibLsp/JsonRpc/, $(JSONRPC_FILES))
+
+HEADERS = $(shell find ./LibLsp ./network -regex ".*\.\(h\|hpp\)")
+
+default: liblspcpp.a headers.tar.gz
+
+liblspcpp.a: $(OFILES)
+ ar -r $@ $^
+
+headers.tar.gz: $(HEADERS) macro_map.h
+ tar -czf $@ $^
+
+%.o: %.cpp
+ $(CXX) $(ALL_CXXFLAGS) $< -c -o $@
+
+clean:
+ find ./ -name *.o | xargs rm -rf
+ rm -rf *.a *.tar.gz
diff --git a/graphics/asymptote/LspCpp/README.md b/graphics/asymptote/LspCpp/README.md
new file mode 100644
index 0000000000..4c279f7f4a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/README.md
@@ -0,0 +1,48 @@
+# LspCpp
+
+## Dependencies
+`LspCpp` depends on the boost and rapidjson,utfcpp,and threadpool
+
+## Build
+
+### Linux
+ 1. Install boost
+ ```shell
+ $ sudo apt-get install libboost-dev
+ ```
+ 2. [Restore the submodules][4].
+ ```shell
+ $ git submodule init
+ $ git submodule update
+ ```
+ 3. Build it.
+ ```shell
+ $ make
+ ```
+### Windows
+ 1. Open project with Vistual Studio.
+ 2. [Restore packages][3] with Vistual Studio.
+ 3. [Restore the submodules][4].
+ ```shell
+ git submodule init
+ git submodule update
+ ```
+ 4. Build it with Vistual Studio.
+
+## Reference
+ Some code from :[cquery][1]
+
+## Projects using LspCpp:
+* [JCIDE](https://www.javacardos.com/tools)
+* [LPG-language-server](https://github.com/kuafuwang/LPG-language-server)
+## License
+ MIT
+
+## Example:
+[It's here](https://github.com/kuafuwang/LspCpp/tree/master/example)
+
+
+[1]: https://github.com/cquery-project/cquery "cquery:"
+[2]: https://www.javacardos.com/tools "JcKit:"
+[3]: https://docs.microsoft.com/en-us/nuget/consume-packages/package-restore "Package Restore"
+[4]: https://git-scm.com/book/en/v2/Git-Tools-Submodules "Git-Tools-Submodules"
diff --git a/graphics/asymptote/LspCpp/example/StdIOClientExample.cpp b/graphics/asymptote/LspCpp/example/StdIOClientExample.cpp
new file mode 100644
index 0000000000..1c73626a45
--- /dev/null
+++ b/graphics/asymptote/LspCpp/example/StdIOClientExample.cpp
@@ -0,0 +1,221 @@
+
+#include "LibLsp/lsp/ProcessIoService.h"
+#ifdef STDIO_CLIENT_EXAMPLE
+
+#include <boost/program_options.hpp>
+#include "LibLsp/lsp/general/exit.h"
+#include "LibLsp/lsp/textDocument/declaration_definition.h"
+
+#include "LibLsp/lsp/textDocument/signature_help.h"
+#include "LibLsp/lsp/general/initialize.h"
+#include "LibLsp/lsp/ProtocolJsonHandler.h"
+#include "LibLsp/lsp/textDocument/typeHierarchy.h"
+#include "LibLsp/lsp/AbsolutePath.h"
+#include "LibLsp/lsp/textDocument/resolveCompletionItem.h"
+#include <network/uri.hpp>
+#include "LibLsp/JsonRpc/Endpoint.h"
+#include "LibLsp/JsonRpc/stream.h"
+#include "LibLsp/JsonRpc/TcpServer.h"
+#include "LibLsp/lsp/textDocument/document_symbol.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+#include <boost/process.hpp>
+#include <boost/process/windows.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+
+
+using namespace boost::asio::ip;
+using namespace std;
+class DummyLog :public lsp::Log
+{
+public:
+
+ void log(Level level, std::wstring&& msg)
+ {
+
+ std::wcerr << msg << std::endl;
+ };
+ void log(Level level, const std::wstring& msg)
+ {
+ std::wcerr << msg << std::endl;
+ };
+ void log(Level level, std::string&& msg)
+ {
+ std::cerr << msg << std::endl;
+ };
+ void log(Level level, const std::string& msg)
+ {
+ std::cerr << msg << std::endl;
+ };
+};
+
+struct boost_process_ipstream : lsp::base_istream< boost::process::ipstream >
+{
+ explicit boost_process_ipstream(boost::process::ipstream& _t)
+ : base_istream<boost::process::ipstream>(_t)
+ {
+ }
+
+ std::string what() override
+ {
+ return {};
+ }
+ void clear() override
+ {
+
+ }
+};
+struct boost_process_opstream : lsp::base_ostream< boost::process::opstream >
+{
+ explicit boost_process_opstream(boost::process::opstream& _t)
+ : lsp::base_ostream<boost::process::opstream>(_t)
+ {
+ }
+
+ std::string what() override
+ {
+ return {};
+ }
+ void clear() override
+ {
+
+ }
+};
+class Client
+{
+public:
+ Client(std::string& execPath,const std::vector<std::string>& args)
+ :point(protocol_json_handler, endpoint, _log)
+ {
+ std::error_code ec;
+ namespace bp = boost::process;
+ c = std::make_shared<bp::child>(asio_io.getIOService(), execPath,
+ bp::args = args,
+ ec,
+ bp::windows::show_normal,
+ bp::std_out > read_from_service,
+ bp::std_in < write_to_service,
+ bp::on_exit([&](int exit_code, const std::error_code& ec_in){
+
+ }));
+ if (ec)
+ {
+ // fail
+ _log.log(lsp::Log::Level::SEVERE, "Start server failed.");
+ }
+ else {
+ //success
+ point.startProcessingMessages(read_from_service_proxy, write_to_service_proxy);
+ }
+ }
+ ~Client()
+ {
+ point.Stop();
+ ::Sleep(1000);
+
+ }
+
+ lsp::ProcessIoService asio_io;
+ std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared< lsp::ProtocolJsonHandler>();
+ DummyLog _log;
+
+ std::shared_ptr<GenericEndpoint> endpoint = std::make_shared<GenericEndpoint>(_log);
+
+ boost::process::opstream write_to_service;
+ boost::process::ipstream read_from_service;
+
+ std::shared_ptr<lsp::ostream> write_to_service_proxy = std::make_shared<boost_process_opstream>(write_to_service);
+ std::shared_ptr<lsp::istream> read_from_service_proxy = std::make_shared< boost_process_ipstream >(read_from_service);
+
+ std::shared_ptr<boost::process::child> c;
+ RemoteEndPoint point;
+};
+
+int main(int argc, char* argv[])
+{
+ using namespace boost::program_options;
+ options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "produce help message")
+ ("execPath", value<string>(), "LSP server's path");
+
+
+
+ variables_map vm;
+ try {
+ store(parse_command_line(argc, argv, desc), vm);
+ }
+ catch (std::exception& e) {
+ std::cout << "Undefined input.Reason:" << e.what() << std::endl;
+ return 0;
+ }
+ notify(vm);
+
+
+ if (vm.count("help"))
+ {
+ cout << desc << endl;
+ return 1;
+ }
+ string execPath;
+ if (vm.count("execPath"))
+ {
+ execPath = vm["execPath"].as<string>();
+ }
+ else
+ {
+ execPath = "STDIO_SERVER_EXAMPLE.exe";
+ }
+
+ Client client(execPath, {});
+ {
+ td_initialize::request req;
+ auto rsp = client.point.waitResponse(req);
+ if (rsp)
+ {
+ std::cerr << rsp->ToJson() << std::endl;
+ }
+ else
+ {
+ std::cerr << "get initialze response time out" << std::endl;
+ }
+ }
+ {
+ td_definition::request req;
+ auto future_rsp = client.point.send(req);
+ auto state = future_rsp.wait_for(std::chrono::seconds(4));
+ if (std::future_status::timeout == state)
+ {
+ std::cerr << "get textDocument/definition response time out" << std::endl;
+ return 0;
+ }
+ auto rsp = future_rsp.get();
+ if (rsp.is_error)
+ {
+ std::cerr << "get textDocument/definition response error" << std::endl;
+
+ }
+ else
+ {
+ std::cerr << rsp.response.ToJson() << std::endl;
+ }
+ }
+ {
+ td_initialize::request req;
+ auto rsp = client.point.waitResponse(req);
+ if (rsp)
+ {
+ std::cerr << rsp->ToJson() << std::endl;
+ }
+ else
+ {
+ std::cerr << "get initialze response time out" << std::endl;
+ }
+ }
+ Notify_Exit::notify notify;
+ client.point.send(notify);
+ return 0;
+}
+#endif
+
diff --git a/graphics/asymptote/LspCpp/example/StdIOServerExample.cpp b/graphics/asymptote/LspCpp/example/StdIOServerExample.cpp
new file mode 100644
index 0000000000..60b0d04db0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/example/StdIOServerExample.cpp
@@ -0,0 +1,162 @@
+#include "LibLsp/JsonRpc/Condition.h"
+#ifdef STDIO_SERVER_EXAMPLE
+
+#include "LibLsp/lsp/general/exit.h"
+#include "LibLsp/lsp/textDocument/declaration_definition.h"
+#include <boost/program_options.hpp>
+#include "LibLsp/lsp/textDocument/signature_help.h"
+#include "LibLsp/lsp/general/initialize.h"
+#include "LibLsp/lsp/ProtocolJsonHandler.h"
+#include "LibLsp/lsp/textDocument/typeHierarchy.h"
+#include "LibLsp/lsp/AbsolutePath.h"
+#include "LibLsp/lsp/textDocument/resolveCompletionItem.h"
+#include <network/uri.hpp>
+
+
+#include "LibLsp/JsonRpc/Endpoint.h"
+#include "LibLsp/JsonRpc/stream.h"
+#include "LibLsp/JsonRpc/TcpServer.h"
+#include "LibLsp/lsp/textDocument/document_symbol.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+#include <boost/process.hpp>
+#include <boost/process/windows.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+using namespace boost::asio::ip;
+using namespace std;
+class DummyLog :public lsp::Log
+{
+public:
+
+ void log(Level level, std::wstring&& msg)
+ {
+
+ std::wcerr << msg << std::endl;
+ };
+ void log(Level level, const std::wstring& msg)
+ {
+ std::wcerr << msg << std::endl;
+ };
+ void log(Level level, std::string&& msg)
+ {
+ std::cerr << msg << std::endl;
+ };
+ void log(Level level, const std::string& msg)
+ {
+ std::cerr << msg << std::endl;
+ };
+};
+
+
+class StdIOServer
+{
+public:
+
+ StdIOServer() : remote_end_point_(protocol_json_handler, endpoint, _log)
+ {
+ remote_end_point_.registerHandler([&](const td_initialize::request& req)
+ {
+ td_initialize::response rsp;
+ rsp.id = req.id;
+ CodeLensOptions code_lens_options;
+ code_lens_options.resolveProvider = true;
+ rsp.result.capabilities.codeLensProvider = code_lens_options;
+ return rsp;
+ });
+
+ remote_end_point_.registerHandler([&](Notify_Exit::notify& notify)
+ {
+ remote_end_point_.Stop();
+ esc_event.notify(std::make_unique<bool>(true));
+ });
+ remote_end_point_.registerHandler([&](const td_definition::request& req,
+ const CancelMonitor& monitor)
+ {
+ td_definition::response rsp;
+ rsp.result.first = std::vector<lsLocation>();
+ if (monitor && monitor())
+ {
+ _log.info("textDocument/definition request had been cancel.");
+ }
+ return rsp;
+ });
+
+ remote_end_point_.startProcessingMessages(input, output);
+ }
+ ~StdIOServer()
+ {
+
+ }
+
+ struct ostream : lsp::base_ostream<std::ostream>
+ {
+ explicit ostream(std::ostream& _t)
+ : base_ostream<std::ostream>(_t)
+ {
+
+ }
+
+ std::string what() override
+ {
+ return {};
+ }
+ };
+ struct istream :lsp::base_istream<std::istream>
+ {
+ explicit istream(std::istream& _t)
+ : base_istream<std::istream>(_t)
+ {
+ }
+
+ std::string what() override
+ {
+ return {};
+ }
+ };
+ std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared < lsp::ProtocolJsonHandler >();
+ DummyLog _log;
+
+ std::shared_ptr<ostream> output = std::make_shared<ostream>(std::cout);
+ std::shared_ptr<istream> input = std::make_shared<istream>(std::cin);
+
+ std::shared_ptr < GenericEndpoint > endpoint = std::make_shared<GenericEndpoint>(_log);
+ RemoteEndPoint remote_end_point_;
+ Condition<bool> esc_event;
+};
+
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace boost::program_options;
+ options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "produce help message");
+
+
+
+ variables_map vm;
+ try {
+ store(parse_command_line(argc, argv, desc), vm);
+ }
+ catch (std::exception& e) {
+ std::cout << "Undefined input.Reason:" << e.what() << std::endl;
+ return 0;
+ }
+ notify(vm);
+
+
+ if (vm.count("help"))
+ {
+ cout << desc << endl;
+ return 1;
+ }
+ StdIOServer server;
+ server.esc_event.wait();
+
+ return 0;
+}
+#endif
+
diff --git a/graphics/asymptote/LspCpp/example/TcpServerExample.cpp b/graphics/asymptote/LspCpp/example/TcpServerExample.cpp
new file mode 100644
index 0000000000..1b717aeca4
--- /dev/null
+++ b/graphics/asymptote/LspCpp/example/TcpServerExample.cpp
@@ -0,0 +1,200 @@
+#ifdef TCP_SERVER_EXAMPLE
+
+#include "LibLsp/lsp/general/exit.h"
+#include "LibLsp/lsp/textDocument/declaration_definition.h"
+#include "LibLsp/lsp/textDocument/signature_help.h"
+#include "LibLsp/lsp/general/initialize.h"
+#include "LibLsp/lsp/ProtocolJsonHandler.h"
+#include "LibLsp/lsp/textDocument/typeHierarchy.h"
+#include "LibLsp/lsp/AbsolutePath.h"
+#include "LibLsp/lsp/textDocument/resolveCompletionItem.h"
+#include <network/uri.hpp>
+
+
+#include "LibLsp/JsonRpc/Endpoint.h"
+#include "LibLsp/JsonRpc/stream.h"
+#include "LibLsp/JsonRpc/TcpServer.h"
+#include "LibLsp/lsp/textDocument/document_symbol.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+using namespace boost::asio::ip;
+using namespace std;
+class DummyLog :public lsp::Log
+{
+public:
+
+ void log(Level level, std::wstring&& msg)
+ {
+ std::wcout << msg << std::endl;
+ };
+ void log(Level level, const std::wstring& msg)
+ {
+ std::wcout << msg << std::endl;
+ };
+ void log(Level level, std::string&& msg)
+ {
+ std::cout << msg << std::endl;
+ };
+ void log(Level level, const std::string& msg)
+ {
+ std::cout << msg << std::endl;
+ };
+};
+
+std::string _address = "127.0.0.1";
+std::string _port = "9333";
+
+class Server
+{
+public:
+
+
+ Server():server(_address,_port,protocol_json_handler, endpoint, _log)
+ {
+ server.point.registerHandler(
+ [&](const td_initialize::request& req)
+ ->lsp::ResponseOrError< td_initialize::response >{
+
+ td_initialize::response rsp;
+ CodeLensOptions code_lens_options;
+ code_lens_options.resolveProvider = true;
+ rsp.result.capabilities.codeLensProvider = code_lens_options;
+
+ return rsp;
+ });
+ server.point.registerHandler([&](const td_definition::request& req
+ ,const CancelMonitor& monitor)
+ {
+ td_definition::response rsp;
+ rsp.result.first= std::vector<lsLocation>();
+ std::this_thread::sleep_for(std::chrono::seconds(8));
+ if(monitor && monitor())
+ {
+ _log.info("textDocument/definition request had been cancel.");
+ }
+ return rsp;
+ });
+
+ server.point.registerHandler([=](Notify_Exit::notify& notify)
+ {
+ std::cout << notify.ToJson() << std::endl;
+ });
+ std::thread([&]()
+ {
+ server.run();
+ }).detach();
+ }
+ ~Server()
+ {
+ server.stop();
+ }
+ std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared < lsp::ProtocolJsonHandler >();
+ DummyLog _log;
+
+ std::shared_ptr < GenericEndpoint > endpoint = std::make_shared<GenericEndpoint>(_log);
+ lsp::TcpServer server;
+
+};
+
+class Client
+{
+public:
+ struct iostream :public lsp::base_iostream<tcp::iostream>
+ {
+ explicit iostream(boost::asio::basic_socket_iostream<tcp>& _t)
+ : base_iostream<boost::asio::basic_socket_iostream<tcp>>(_t)
+ {
+ }
+
+ std::string what() override
+ {
+ auto msg = _impl.error().message();
+ return msg;
+ }
+
+ };
+ Client() :remote_end_point_(protocol_json_handler, endpoint, _log)
+ {
+ tcp::endpoint end_point( address::from_string(_address), 9333);
+
+ socket_ = std::make_shared<tcp::iostream>();
+ socket_->connect(end_point);
+ if (!socket_)
+ {
+ string temp = "Unable to connect: " + socket_->error().message();
+ std::cout << temp << std::endl;
+ }
+
+ vector<string> args;
+ socket_proxy = std::make_shared<iostream>(*socket_.get());
+
+ remote_end_point_.startProcessingMessages(socket_proxy, socket_proxy);
+ }
+ ~Client()
+ {
+ remote_end_point_.Stop();
+ ::Sleep(1000);
+ socket_->close();
+ }
+
+ std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared< lsp::ProtocolJsonHandler>();
+ DummyLog _log;
+
+ std::shared_ptr<GenericEndpoint> endpoint = std::make_shared<GenericEndpoint>(_log);
+
+ std::shared_ptr < iostream> socket_proxy;
+ std::shared_ptr<tcp::iostream> socket_;
+ RemoteEndPoint remote_end_point_;
+};
+
+int main()
+{
+
+ Server server;
+ Client client;
+
+ {
+ td_initialize::request req;
+ auto rsp = client.remote_end_point_.waitResponse(req);
+ if (rsp)
+ {
+ std::cout << rsp->response.ToJson() << std::endl;
+ }
+ else
+ {
+ std::cout << "get initialze response time out" << std::endl;
+ }
+ }
+ {
+ td_definition::request req;
+ auto future_rsp = client.remote_end_point_.send(req);
+ Notify_Cancellation::notify cancel_notify;
+ cancel_notify.params.id = req.id;
+ client.remote_end_point_.send(cancel_notify);
+
+ auto state = future_rsp.wait_for(std::chrono::seconds(16));
+ if (std::future_status::timeout == state)
+ {
+ std::cout << "get textDocument/definition response time out" << std::endl;
+ return 0;
+ }
+ auto rsp = future_rsp.get();
+ if (rsp.is_error)
+ {
+ std::cout << "get textDocument/definition response error" << std::endl;
+
+ }
+ else
+ {
+ std::cout << rsp.response.ToJson() << std::endl;
+ }
+ }
+ Notify_Exit::notify notify;
+ client.remote_end_point_.send(notify);
+ return 0;
+}
+#endif
+
diff --git a/graphics/asymptote/LspCpp/example/WebsocketExample.cpp b/graphics/asymptote/LspCpp/example/WebsocketExample.cpp
new file mode 100644
index 0000000000..e82f0a96f9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/example/WebsocketExample.cpp
@@ -0,0 +1,297 @@
+#ifdef WEBSOCKET_SERVER_EXAMPLE
+
+#include "LibLsp/JsonRpc/WebSocketServer.h"
+#include "LibLsp/lsp/textDocument/signature_help.h"
+#include "LibLsp/lsp/general/initialize.h"
+#include "LibLsp/lsp/ProtocolJsonHandler.h"
+#include "LibLsp/lsp/textDocument/typeHierarchy.h"
+#include "LibLsp/lsp/AbsolutePath.h"
+#include "LibLsp/lsp/textDocument/resolveCompletionItem.h"
+#include <network/uri.hpp>
+
+
+#include "LibLsp/JsonRpc/Endpoint.h"
+#include "LibLsp/JsonRpc/stream.h"
+#include "LibLsp/JsonRpc/TcpServer.h"
+#include "LibLsp/lsp/textDocument/document_symbol.h"
+#include "LibLsp/lsp/workspace/execute_command.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <boost/beast/version.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/dispatch.hpp>
+#include "LibLsp/JsonRpc/Endpoint.h"
+#include "LibLsp/JsonRpc/RemoteEndPoint.h"
+#include "LibLsp/JsonRpc/stream.h"
+#include "LibLsp/lsp/ProtocolJsonHandler.h"
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+std::string _address = "127.0.0.1";
+std::string _port = "9333";
+
+
+
+
+using namespace std;
+class DummyLog :public lsp::Log
+{
+public:
+
+ void log(Level level, std::wstring&& msg)
+ {
+ std::wcout << msg << std::endl;
+ };
+ void log(Level level, const std::wstring& msg)
+ {
+ std::wcout << msg << std::endl;
+ };
+ void log(Level level, std::string&& msg)
+ {
+ std::cout << msg << std::endl;
+ };
+ void log(Level level, const std::string& msg)
+ {
+ std::cout << msg << std::endl;
+ };
+};
+
+
+
+// Sends a WebSocket message and prints the response
+class Client : public std::enable_shared_from_this<Client>
+{
+ net::io_context ioc;
+ tcp::resolver resolver_;
+ websocket::stream<beast::tcp_stream> ws_;
+ beast::flat_buffer buffer_;
+ std::string host_;
+ std::string user_agent_;
+ std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared< lsp::ProtocolJsonHandler>();
+ DummyLog _log;
+
+ std::shared_ptr<GenericEndpoint> endpoint = std::make_shared<GenericEndpoint>(_log);
+
+ std::shared_ptr<lsp::websocket_stream_wrapper> proxy_;
+public:
+ RemoteEndPoint point;
+
+public:
+ // Resolver and socket require an io_context
+ explicit
+ Client()
+ : resolver_(net::make_strand(ioc))
+ , ws_(net::make_strand(ioc)),point(protocol_json_handler, endpoint, _log)
+ {
+ proxy_ = std::make_shared<lsp::websocket_stream_wrapper>(ws_);
+
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port, char const* user_agent)
+ {
+ // Save these for later
+ host_ = host;
+ user_agent_ = user_agent;
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &Client::on_resolve,
+ shared_from_this()));
+ std::thread([&]
+ {
+ ioc.run();
+ }).detach();
+ while (!point.IsWorking())
+ {
+ ::Sleep(50);
+ }
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if (ec)
+ return;
+
+ // Set the timeout for the operation
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(ws_).async_connect(
+ results,
+ beast::bind_front_handler(
+ &Client::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
+ {
+ if (ec)
+ return;
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws_).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::client));
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [=](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ user_agent_.c_str());
+ }));
+
+ // Perform the websocket handshake
+ ws_.async_handshake(host_, "/",
+ beast::bind_front_handler(
+ &Client::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if (ec)
+ return;
+
+ // Send the message
+
+
+ point.startProcessingMessages(proxy_, proxy_);
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &Client::on_read,
+ shared_from_this()));
+ }
+
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if (ec)
+ return;
+
+ char* data = reinterpret_cast<char*>(buffer_.data().data());
+ std::vector<char> elements(data, data + bytes_transferred);
+ buffer_.clear();
+ proxy_->on_request.EnqueueAll(std::move(elements), false);
+
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &Client::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_close(beast::error_code ec)
+ {
+ if (ec)
+ return;
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer_.data()) << std::endl;
+ }
+};
+
+class Server
+{
+public:
+ Server(const std::string& user_agent) : server(user_agent,_address, _port, protocol_json_handler, endpoint, _log)
+ {
+ server.point.registerHandler(
+ [&](const td_initialize::request& req)
+ {
+ td_initialize::response rsp;
+ CodeLensOptions code_lens_options;
+ code_lens_options.resolveProvider = true;
+ rsp.result.capabilities.codeLensProvider = code_lens_options;
+ return rsp;
+ });
+ std::thread([&]()
+ {
+ server.run();
+ }).detach();
+ }
+ ~Server()
+ {
+ server.stop();
+ }
+ std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared < lsp::ProtocolJsonHandler >();
+ DummyLog _log;
+
+ std::shared_ptr < GenericEndpoint > endpoint = std::make_shared<GenericEndpoint>(_log);
+ lsp::WebSocketServer server;
+
+};
+
+int main()
+{
+ std::string user_agent = std::string(BOOST_BEAST_VERSION_STRING) +" websocket-server-async";
+ Server server(user_agent);
+
+ auto client = std::make_shared<Client>();
+ user_agent = std::string(BOOST_BEAST_VERSION_STRING) + " websocket-client-async";
+ client->run(_address.c_str(), _port.c_str(), user_agent.c_str());
+
+ td_initialize::request req;
+
+ auto rsp = client->point.waitResponse(req);
+ if (rsp)
+ {
+ std::cout << rsp->ToJson() << std::endl;
+ }
+ return 0;
+}
+
+
+
+
+
+#endif
+
+
+
diff --git a/graphics/asymptote/LspCpp/macro_map.h b/graphics/asymptote/LspCpp/macro_map.h
new file mode 100644
index 0000000000..f09ba5b1a7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/macro_map.h
@@ -0,0 +1,134 @@
+/*
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+// Taken from https://github.com/cbeck88/visit_struct.
+//
+// Usage
+//
+// #define PRINT_DOUBLE(x) printf(#x " = %d\n", x);
+//
+// MACRO_MAP(PRINT_DOUBLE, 1, 2, 3)
+// #define PRINT_DOUBLES(...) MACRO_MAP(PRINT_DOUBLE, __VA_ARGS__)
+
+#pragma once
+
+static constexpr const int max_visitable_members = 69;
+
+#define VISIT_STRUCT_EXPAND(x) x
+#define VISIT_STRUCT_PP_ARG_N( \
+ _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,\
+ _11, _12, _13, _14, _15, _16, _17, _18, _19, _20,\
+ _21, _22, _23, _24, _25, _26, _27, _28, _29, _30,\
+ _31, _32, _33, _34, _35, _36, _37, _38, _39, _40,\
+ _41, _42, _43, _44, _45, _46, _47, _48, _49, _50,\
+ _51, _52, _53, _54, _55, _56, _57, _58, _59, _60,\
+ _61, _62, _63, _64, _65, _66, _67, _68, _69, N, ...) N
+#define VISIT_STRUCT_PP_NARG(...) VISIT_STRUCT_EXPAND(VISIT_STRUCT_PP_ARG_N(__VA_ARGS__, \
+ 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, \
+ 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
+ 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
+ 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
+ 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
+ 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+
+/* need extra level to force extra eval */
+#define VISIT_STRUCT_CONCAT_(a,b) a ## b
+#define VISIT_STRUCT_CONCAT(a,b) VISIT_STRUCT_CONCAT_(a,b)
+
+#define VISIT_STRUCT_APPLYF0(f)
+#define VISIT_STRUCT_APPLYF1(f,_1) f(_1)
+#define VISIT_STRUCT_APPLYF2(f,_1,_2) f(_1) f(_2)
+#define VISIT_STRUCT_APPLYF3(f,_1,_2,_3) f(_1) f(_2) f(_3)
+#define VISIT_STRUCT_APPLYF4(f,_1,_2,_3,_4) f(_1) f(_2) f(_3) f(_4)
+#define VISIT_STRUCT_APPLYF5(f,_1,_2,_3,_4,_5) f(_1) f(_2) f(_3) f(_4) f(_5)
+#define VISIT_STRUCT_APPLYF6(f,_1,_2,_3,_4,_5,_6) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6)
+#define VISIT_STRUCT_APPLYF7(f,_1,_2,_3,_4,_5,_6,_7) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7)
+#define VISIT_STRUCT_APPLYF8(f,_1,_2,_3,_4,_5,_6,_7,_8) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8)
+#define VISIT_STRUCT_APPLYF9(f,_1,_2,_3,_4,_5,_6,_7,_8,_9) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9)
+#define VISIT_STRUCT_APPLYF10(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10)
+#define VISIT_STRUCT_APPLYF11(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11)
+#define VISIT_STRUCT_APPLYF12(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12)
+#define VISIT_STRUCT_APPLYF13(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13)
+#define VISIT_STRUCT_APPLYF14(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14)
+#define VISIT_STRUCT_APPLYF15(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15)
+#define VISIT_STRUCT_APPLYF16(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16)
+#define VISIT_STRUCT_APPLYF17(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17)
+#define VISIT_STRUCT_APPLYF18(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18)
+#define VISIT_STRUCT_APPLYF19(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19)
+#define VISIT_STRUCT_APPLYF20(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20)
+#define VISIT_STRUCT_APPLYF21(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21)
+#define VISIT_STRUCT_APPLYF22(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22)
+#define VISIT_STRUCT_APPLYF23(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23)
+#define VISIT_STRUCT_APPLYF24(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24)
+#define VISIT_STRUCT_APPLYF25(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25)
+#define VISIT_STRUCT_APPLYF26(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26)
+#define VISIT_STRUCT_APPLYF27(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27)
+#define VISIT_STRUCT_APPLYF28(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28)
+#define VISIT_STRUCT_APPLYF29(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29)
+#define VISIT_STRUCT_APPLYF30(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30)
+#define VISIT_STRUCT_APPLYF31(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31)
+#define VISIT_STRUCT_APPLYF32(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32)
+#define VISIT_STRUCT_APPLYF33(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33)
+#define VISIT_STRUCT_APPLYF34(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34)
+#define VISIT_STRUCT_APPLYF35(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35)
+#define VISIT_STRUCT_APPLYF36(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36)
+#define VISIT_STRUCT_APPLYF37(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37)
+#define VISIT_STRUCT_APPLYF38(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38)
+#define VISIT_STRUCT_APPLYF39(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39)
+#define VISIT_STRUCT_APPLYF40(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40)
+#define VISIT_STRUCT_APPLYF41(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41)
+#define VISIT_STRUCT_APPLYF42(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42)
+#define VISIT_STRUCT_APPLYF43(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43)
+#define VISIT_STRUCT_APPLYF44(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44)
+#define VISIT_STRUCT_APPLYF45(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45)
+#define VISIT_STRUCT_APPLYF46(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46)
+#define VISIT_STRUCT_APPLYF47(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47)
+#define VISIT_STRUCT_APPLYF48(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48)
+#define VISIT_STRUCT_APPLYF49(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49)
+#define VISIT_STRUCT_APPLYF50(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50)
+#define VISIT_STRUCT_APPLYF51(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51)
+#define VISIT_STRUCT_APPLYF52(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52)
+#define VISIT_STRUCT_APPLYF53(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53)
+#define VISIT_STRUCT_APPLYF54(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54)
+#define VISIT_STRUCT_APPLYF55(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55)
+#define VISIT_STRUCT_APPLYF56(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56)
+#define VISIT_STRUCT_APPLYF57(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57)
+#define VISIT_STRUCT_APPLYF58(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58)
+#define VISIT_STRUCT_APPLYF59(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59)
+#define VISIT_STRUCT_APPLYF60(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60)
+#define VISIT_STRUCT_APPLYF61(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61)
+#define VISIT_STRUCT_APPLYF62(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62)
+#define VISIT_STRUCT_APPLYF63(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63)
+#define VISIT_STRUCT_APPLYF64(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64)
+#define VISIT_STRUCT_APPLYF65(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65)
+#define VISIT_STRUCT_APPLYF66(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66)
+#define VISIT_STRUCT_APPLYF67(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67)
+#define VISIT_STRUCT_APPLYF68(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) f(_68)
+#define VISIT_STRUCT_APPLYF69(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68,_69) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) f(_68) f(_69)
+
+#define VISIT_STRUCT_APPLY_F_(M, ...) VISIT_STRUCT_EXPAND(M(__VA_ARGS__))
+#define MACRO_MAP(f, ...) VISIT_STRUCT_EXPAND(VISIT_STRUCT_APPLY_F_(VISIT_STRUCT_CONCAT(VISIT_STRUCT_APPLYF, VISIT_STRUCT_PP_NARG(__VA_ARGS__)), f, __VA_ARGS__))
diff --git a/graphics/asymptote/LspCpp/network/optional.hpp b/graphics/asymptote/LspCpp/network/optional.hpp
new file mode 100644
index 0000000000..43b1cf1fd8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/optional.hpp
@@ -0,0 +1,711 @@
+// Copyright 2016 Glyn Matthews.
+// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file
+ * \brief Contains an implementation of C++17 optional (n3793).
+ *
+ * \sa https://github.com/akrzemi1/Optional
+ * \sa http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html
+ */
+
+#ifndef NETWORK_OPTIONAL_INC
+#define NETWORK_OPTIONAL_INC
+
+#include <stdexcept>
+#include <type_traits>
+#include <utility>
+#include <memory>
+#include <algorithm>
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#ifdef NDEBUG
+#define NETWORK_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
+#else
+#define NETWORK_ASSERTED_EXPRESSION(CHECK, EXPR) \
+ ((CHECK) ? (EXPR) : (fail(#CHECK, __FILE__, __LINE__), (EXPR)))
+inline void fail(const char*, const char*, unsigned) {}
+#endif // NDEBUG
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+namespace network {
+/**
+ * \ingroup optional
+ * \class nullopt_t optional.hpp network/uri.hpp
+ * \brief Disengaged state indicator.
+ * \sa optional
+ */
+struct nullopt_t {
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ struct init {};
+ constexpr nullopt_t(init) {}
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+};
+
+/**
+ * \ingroup optional
+ * \brief Used to indicate a *disengaged* state for optional objects.
+ */
+constexpr nullopt_t nullopt{nullopt_t::init{}};
+
+/**
+ * \ingroup optional
+ * \class bad_optional_access optional.hpp network/uri.hpp
+ * \brief Exception thrown when the value member function is called when the
+ * optional object is disengaged.
+ */
+class bad_optional_access : public std::logic_error {
+ public:
+
+ /**
+ * \brief Constructor.
+ * \param what_arg The error message.
+ */
+ explicit bad_optional_access(const std::string& what_arg)
+ : std::logic_error(what_arg) {}
+
+ /**
+ * \brief Constructor.
+ * \param what_arg The error message.
+ */
+ explicit bad_optional_access(const char* what_arg)
+ : std::logic_error(what_arg) {}
+};
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+namespace details {
+struct dummy_t {};
+
+template <class T>
+union trivially_destructible_optional_storage {
+ static_assert(std::is_trivially_destructible<T>::value, "");
+
+ dummy_t dummy_;
+ T value_;
+
+ constexpr trivially_destructible_optional_storage() : dummy_{} {}
+
+ constexpr trivially_destructible_optional_storage(const T& v) : value_{v} {}
+
+ ~trivially_destructible_optional_storage() = default;
+};
+
+template <class T>
+union optional_storage {
+ dummy_t dummy_;
+ T value_;
+
+ constexpr optional_storage() : dummy_{} {}
+
+ constexpr optional_storage(const T& v) : value_{v} {}
+
+ ~optional_storage() {}
+};
+
+template <class T>
+class trivially_destructible_optional_base {
+public:
+ typedef T value_type;
+
+ constexpr trivially_destructible_optional_base() noexcept
+ : init_(false),
+ storage_{} {}
+
+ constexpr trivially_destructible_optional_base(const T& v)
+ : init_(true), storage_{v} {}
+
+ constexpr trivially_destructible_optional_base(T&& v)
+ : init_(true), storage_{std::move(v)} {}
+
+ ~trivially_destructible_optional_base() = default;
+
+protected:
+
+ bool init_;
+ optional_storage<T> storage_;
+};
+
+template <class T>
+class optional_base {
+public:
+ typedef T value_type;
+
+ constexpr optional_base() noexcept
+ : init_(false),
+ storage_{} {}
+
+ constexpr optional_base(const T& v)
+ : init_(true), storage_{v} {}
+
+ constexpr optional_base(T&& v)
+ : init_(true), storage_{std::move(v)} {}
+
+ ~optional_base() {
+ if (init_) {
+ storage_.value_.T::~T();
+ }
+ }
+
+protected:
+
+ bool init_;
+ optional_storage<T> storage_;
+};
+} // namespace details
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+/**
+ * \ingroup optional
+ * \class optional optional.hpp network/uri.hpp
+ * \brief An implementation of C++17 optional (n3793)
+ */
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+template <class T>
+using optional_base = typename std::conditional<
+ std::is_trivially_destructible<T>::value,
+ details::trivially_destructible_optional_base<T>,
+ details::optional_base<T>>::type;
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+template <class T>
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+class optional : optional_base<T> {
+#else
+class optional {
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ typedef optional_base<T> base_type;
+
+ public:
+ /**
+ * \brief Optional value type.
+ */
+ typedef T value_type;
+
+ /**
+ * \brief Constructor.
+ * \post *disengaged*.
+ */
+ constexpr optional() : optional_base<T>() {}
+
+ /**
+ * \brief Constructor.
+ * \post *disengaged*.
+ */
+ constexpr optional(nullopt_t) noexcept : optional_base<T>() {}
+
+ /**
+ * \brief Copy constructor.
+ * \param other The other optional object.
+ */
+ optional(const optional& other) {
+ if (other) {
+ ::new(static_cast<void*>(ptr())) T(*other);
+ base_type::init_ = true;
+ }
+ }
+
+ /**
+ * \brief Move constructor.
+ * \param other The other optional object.
+ */
+ optional(optional&& other) noexcept {
+ if (other) {
+ ::new(static_cast<void*>(ptr())) T(std::move(other.storage_.value_));
+ base_type::init_ = true;
+ }
+ }
+
+ /**
+ * \brief Constructor.
+ * \param value The value with which to initialize the optional object.
+ * \post *engaged*
+ */
+ constexpr optional(const T& value) : optional_base<T>(value) {}
+
+ /**
+ * \brief Constructor.
+ * \param value The value with which to initialize the optional object.
+ * \post *engaged*
+ */
+ constexpr optional(T&& value) : optional_base<T>(std::move(value)) {}
+
+ /**
+ * \brief Assignment operator.
+ * \post *disengaged*.
+ * \returns \c *this.
+ */
+ optional& operator=(nullopt_t) noexcept {
+ if (base_type::init_) {
+ ptr()->T::~T();
+ }
+ base_type::init_ = false;
+ return *this;
+ }
+
+ /**
+ * \brief Copy assignment operator.
+ * \param other The other optional object.
+ * \returns \c *this.
+ */
+ optional& operator=(const optional& other) {
+ if (bool(*this) && !other) {
+ ptr()->T::~T();
+ base_type::init_ = false;
+ }
+ else if (!(*this) && bool(other)) {
+ ::new(static_cast<void*>(ptr())) T(*other);
+ base_type::init_ = true;
+ }
+ else if (bool(*this) && bool(other)) {
+ base_type::storage_.value_ = *other;
+ }
+ return *this;
+ }
+
+ /**
+ * \brief Move assignment operator.
+ * \param other The other optional object.
+ * \returns \c *this.
+ */
+ optional& operator=(optional&& other) noexcept {
+ if (bool(*this) && !other) {
+ ptr()->T::~T();
+ base_type::init_ = false;
+ }
+ else if (!(*this) && bool(other)) {
+ ::new(static_cast<void*>(ptr())) T(std::move(*other));
+ base_type::init_ = true;
+ }
+ else if (bool(*this) && bool(other)) {
+ base_type::storage_.value_ = std::move(*other);
+ }
+ return *this;
+ }
+
+ /**
+ * \brief Destructor.
+ */
+ ~optional() = default;
+
+ /**
+ * \brief Swap function.
+ * \param other The other optional object.
+ */
+ void swap(optional& other) noexcept {
+ if (bool(*this) && !other) {
+ ::new(static_cast<void*>(other.ptr())) T(std::move(**this));
+ ptr()->T::~T();
+ std::swap(base_type::init_, other.base_type::init_);
+ }
+ else if (!(*this) && bool(other)) {
+ ::new(static_cast<void*>(ptr())) T(std::move(*other));
+ other.ptr()->T::~T();
+ std::swap(base_type::init_, other.init_);
+ }
+ else if (bool(*this) && bool(other)) {
+ std::swap(**this, *other);
+ }
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ constexpr T const* operator->() const {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), ptr());
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ T* operator->() {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), ptr());
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ constexpr T const& operator*() const {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), base_type::storage_.value_);
+ }
+
+ /**
+ * \brief Observer.
+ * \pre *engaged*
+ * \returns The underlying optional value.
+ */
+ T& operator*() {
+ return NETWORK_ASSERTED_EXPRESSION(bool(*this), base_type::storage_.value_);
+ }
+
+ /**
+ * \brief Operator bool overloads.
+ * \returns \c true if the optional is *engaged*, \c false if it is *disengaged*.
+ */
+ constexpr explicit operator bool() const noexcept { return base_type::init_; }
+
+ /**
+ * \returns The underlying optional value, if \c bool(*this).
+ * \throws A bad_optional_access if \c !*this.
+ */
+ constexpr T const& value() const {
+ return *this ? base_type::storage_.value_
+ : (throw bad_optional_access("Uninitialized optional value"),
+ base_type::storage_.value_);
+ }
+ /**
+ * \returns The underlying optional value, if \c bool(*this).
+ * \throws A bad_optional_access if \c !*this.
+ */
+ T& value() {
+ return *this ? base_type::storage_.value_
+ : (throw bad_optional_access("Uninitialized optional value"),
+ base_type::storage_.value_);
+ }
+
+ /**
+ * \returns <tt>bool(*this) ? **this : static_cast<T>(std::forward<U>(v))</tt>.
+ * \pre \c <tt>std::is_copy_constructible<T>::value</tt> is \c true and <tt>std::is_convertible<U&&, T>::value</tt> is \c true.
+ */
+ template <class U>
+ T value_or(U&& other) const & {
+ static_assert(std::is_copy_constructible<value_type>::value, "Must be copy constructible.");
+ static_assert(std::is_convertible<U, value_type>::value, "U must be convertible to T.");
+ return bool(*this) ? **this : static_cast<T>(std::forward<U>(other));
+ }
+
+ /**
+ * \returns <tt>bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v))</tt>.
+ * \pre <tt>std::is_move_constructible<T>::value</tt> is \c true and <tt>std::is_convertible<U&&, T>::value</tt> is \c true.
+ */
+ template <class U>
+ T value_or(U&& other) && {
+ static_assert(std::is_copy_constructible<value_type>::value, "Must be copy constructible.");
+ static_assert(std::is_convertible<U, value_type>::value, "U must be convertible to T.");
+ return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(other));
+ }
+
+ private:
+
+ T* ptr() {
+ return std::addressof(base_type::storage_.value_);
+ }
+
+};
+
+/**
+ * \brief Equality operator.
+ */
+template <class T>
+bool operator==(const optional<T>& lhs, const optional<T>& rhs) {
+ if (bool(lhs) != bool(rhs)) {
+ return false;
+ } else if (!bool(lhs)) {
+ return true;
+ } else {
+ return *lhs == *rhs;
+ }
+}
+
+/**
+ * \brief Inequality operator.
+ */
+template <class T>
+bool operator!=(const optional<T>& lhs, const optional<T>& rhs) {
+ return !(lhs == rhs);
+}
+
+/**
+ * \brief Comparison operator.
+ */
+template <class T>
+bool operator<(const optional<T>& lhs, const optional<T>& rhs) {
+ if (!rhs) {
+ return false;
+ } else if (!lhs) {
+ return true;
+ } else {
+ return *lhs < *rhs;
+ }
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>rhs < lhs</tt>.
+ */
+template <class T>
+bool operator>(const optional<T>& lhs, const optional<T>& rhs) {
+ return rhs < lhs;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(rhs < lhs)</tt>.
+ */
+template <class T>
+bool operator<=(const optional<T>& lhs, const optional<T>& rhs) {
+ return !(rhs < lhs);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(rhs > lhs)</tt>.
+ */
+template <class T>
+bool operator>=(const optional<T>& lhs, const optional<T>& rhs) {
+ return !(lhs < rhs);
+}
+
+/**
+ * \brief Equality operator.
+ * \returns \c !x.
+ */
+template <class T>
+bool operator==(const optional<T>& x, nullopt_t) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Equality operator.
+ * \returns \c !x.
+ */
+template <class T>
+bool operator==(nullopt_t, const optional<T>& x) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns \c bool(x).
+ */
+template <class T>
+bool operator!=(const optional<T>& x, nullopt_t) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns \c bool(x).
+ */
+template <class T>
+bool operator!=(nullopt_t, const optional<T>& x) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c false.
+ */
+template <class T>
+bool operator<(const optional<T>& x, nullopt_t) noexcept {
+ return false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c bool(x).
+ */
+template <class T>
+bool operator<(nullopt_t, const optional<T>& x) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c !x.
+ */
+template <class T>
+bool operator<=(const optional<T>& x, nullopt_t) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c true.
+ */
+template <class T>
+bool operator<=(nullopt_t, const optional<T>& x) noexcept {
+ return true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c bool(x).
+ */
+template <class T>
+bool operator>(const optional<T>& x, nullopt_t) noexcept {
+ return bool(x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c false.
+ */
+template <class T>
+bool operator>(nullopt_t, const optional<T>& x) noexcept {
+ return false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c true.
+ */
+template <class T>
+bool operator>=(const optional<T>& x, nullopt_t) noexcept {
+ return true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns \c !x.
+ */
+template <class T>
+bool operator>=(nullopt_t, const optional<T>& x) noexcept {
+ return !x;
+}
+
+/**
+ * \brief Equality operator.
+ * \returns <tt>bool(x) ? *x == v : false</tt>.
+ */
+template <class T>
+bool operator==(const optional<T>& x, const T& v) {
+ return bool(x) ? *x == v : false;
+}
+
+/**
+ * \brief Equality operator.
+ * \returns <tt>bool(x) ? v == *x : false</tt>.
+ */
+template <class T>
+bool operator==(const T& v, const optional<T>& x) {
+ return bool(x) ? v == *x : false;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns <tt>bool(x) ? !(*x == v) : true</tt>.
+ */
+template <class T>
+bool operator!=(const optional<T>& x, const T& v) {
+ return bool(x) ? !(*x == v) : true;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns <tt>bool(x) ? !(v == *x) : true</tt>.
+ */
+template <class T>
+bool operator!=(const T& v, const optional<T>& x) {
+ return bool(x) ? !(v == *x) : true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>bool(x) ? *x < v : true</tt>.
+ */
+template <class T>
+bool operator<(const optional<T>& x, const T& v) {
+ return bool(x) ? *x < v : true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>bool(x) ? v < *x : false</tt>.
+ */
+template <class T>
+bool operator<(const T& v, const optional<T>& x) {
+ return bool(x) ? v < *x : false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>bool(x) ? *x < v : true</tt>.
+ */
+template <class T>
+bool operator>(const optional<T>& x, const T& v) {
+ return bool(x) ? *x < v : true;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>bool(x) ? v < *x : false</tt>.
+ */
+template <class T>
+bool operator>(const T& v, const optional<T>& x) {
+ return bool(x) ? v < *x : false;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(x < v)</tt>.
+ */
+template <class T>
+bool operator>=(const optional<T>& x, const T& v) {
+ return !(x < v);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(v < x)</tt>.
+ */
+template <class T>
+bool operator>=(const T& v, const optional<T>& x) {
+ return !(v < x);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(x > v)</tt>.
+ */
+template <class T>
+bool operator<=(const optional<T>& x, const T& v) {
+ return !(x > v);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(v > x)</tt>.
+ */
+template <class T>
+bool operator<=(const T& v, const optional<T>& x) {
+ return !(v > x);
+}
+
+/**
+ * \ingroup optional
+ * \brief Swap function.
+ * \param lhs The first optional object.
+ * \param rhs The second optional object.
+ *
+ * Calls:
+ * \code{.cpp}
+ * lhs.swap(rhs);
+ * \endcode
+ */
+template <class T>
+inline void swap(optional<T>& lhs,
+ optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
+ return lhs.swap(rhs);
+}
+
+/**
+ * \ingroup optional
+ * \brief A helper function to contruct an optional object.
+ * \returns <tt>optional<typename std::decay<T>::type>(std::forward(value))</tt>.
+ */
+template <class T>
+inline constexpr optional<typename std::decay<T>::type> make_optional(T&& value) {
+ return optional<typename std::decay<T>::type>(std::forward(value));
+}
+} // namespace network
+
+#endif // NETWORK_OPTIONAL_INC
diff --git a/graphics/asymptote/LspCpp/network/string_view.hpp b/graphics/asymptote/LspCpp/network/string_view.hpp
new file mode 100644
index 0000000000..df54e7aa35
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/string_view.hpp
@@ -0,0 +1,273 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_STRING_VIEW_INC
+#define NETWORK_STRING_VIEW_INC
+
+/**
+ * \file
+ * \brief Contains an implementation of C++17 string_view (n3921).
+ */
+
+#include <string>
+#include <iterator>
+#include <cassert>
+#include <stdexcept>
+#include <algorithm>
+
+namespace network {
+/**
+ * \class basic_string_view string_view.hpp network/uri/string_view.hpp
+ * \brief An implementation of C++17 string_view (n3921)
+ */
+template <class charT, class traits = std::char_traits<charT>>
+class basic_string_view {
+ public:
+ typedef traits traits_type;
+ typedef charT value_type;
+ typedef charT* pointer;
+ typedef const charT* const_pointer;
+ typedef charT& reference;
+ typedef const charT& const_reference;
+ typedef const charT* const_iterator;
+ typedef const_iterator iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef const_reverse_iterator reverse_iterator;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ static constexpr size_type npos = size_type(-1);
+
+ /**
+ * \brief Constructor.
+ */
+ constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
+
+ /**
+ * \brief Copy constructor.
+ */
+ constexpr basic_string_view(const basic_string_view&) noexcept = default;
+
+ /**
+ * \brief Assignment operator.
+ */
+ basic_string_view& operator=(const basic_string_view&) noexcept = default;
+
+ /**
+ * \brief Constructor.
+ */
+ template <class Allocator>
+ basic_string_view(
+ const std::basic_string<charT, traits, Allocator>& str) noexcept
+ : data_(str.data()),
+ size_(str.size()) {}
+
+ /**
+ * \brief Constructor.
+ */
+ constexpr basic_string_view(const charT* str)
+ : data_(str), size_(traits::length(str)) {}
+
+ /**
+ * \brief Constructor.
+ */
+ constexpr basic_string_view(const charT* str, size_type len)
+ : data_(str), size_(len) {}
+
+ constexpr const_iterator begin() const noexcept { return data_; }
+
+ constexpr const_iterator end() const noexcept { return data_ + size_; }
+
+ constexpr const_iterator cbegin() const noexcept { return begin(); }
+
+ constexpr const_iterator cend() const noexcept { return end(); }
+
+ const_reverse_iterator rbegin() const noexcept {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ constexpr size_type size() const noexcept { return size_; }
+
+ constexpr size_type length() const noexcept { return size_; }
+
+ constexpr size_type max_size() const noexcept { return size_; }
+
+ constexpr bool empty() const noexcept { return size_ == 0; }
+
+ constexpr const_reference operator[](size_type pos) const {
+ return data_[pos];
+ }
+
+ const_reference at(size_type pos) const {
+ if (pos >= size_) {
+ throw std::out_of_range("Index out of range.");
+ }
+ return data_[pos];
+ }
+
+ const_reference front() const { return *begin(); }
+
+ const_reference back() const {
+ auto last = (end()) - 1;
+ return *last;
+ }
+
+ constexpr const_pointer data() const noexcept { return data_; }
+
+ void clear() noexcept {
+ data_ = nullptr;
+ size_ = 0;
+ }
+
+ void remove_prefix(size_type n) {
+ data_ += n;
+ size_ -= n;
+ }
+
+ void remove_suffix(size_type n) { size_ -= n; }
+
+ void swap(basic_string_view& s) noexcept {
+ std::swap(data_, s.data_);
+ std::swap(size_, s.size_);
+ }
+
+ template <class Allocator>
+ explicit operator std::basic_string<charT, traits, Allocator>() const {
+ return to_string<charT, traits, Allocator>();
+ }
+
+ template <class Allocator = std::allocator<charT>>
+ std::basic_string<charT, traits, Allocator> to_string(
+ const Allocator& a = Allocator()) const {
+ return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
+ }
+
+ size_type copy(charT* s, size_type n, size_type pos = 0) const {
+ size_type rlen = std::min(n, size() - pos);
+ std::copy_n(begin() + pos, rlen, s);
+ return rlen;
+ }
+
+ constexpr basic_string_view substr(size_type pos = 0,
+ size_type n = npos) const {
+ return basic_string_view(data() + pos, std::min(n, size() - pos));
+ }
+
+ constexpr int compare(basic_string_view s) const noexcept {
+ return size() == s.size()
+ ? traits::compare(data(), s.data(), size())
+ : (size() < s.size()
+ ? (traits::compare(data(), s.data(), size()) > 0 ? 1 : -1)
+ : (traits::compare(data(), s.data(), size()) < 0 ? -1
+ : 1));
+ }
+
+ constexpr int compare(size_type pos1, size_type n1,
+ basic_string_view s) const {
+ return substr(pos1, n1).compare(s);
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, basic_string_view s,
+ size_type pos2, size_type n2) const {
+ return substr(pos1, n1).compare(s.substr(pos2, n2));
+ }
+
+ constexpr int compare(const charT* s) const {
+ return compare(basic_string_view(s));
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, const charT* s) const {
+ return substr(pos1, n1).compare(basic_string_view(s));
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, const charT* s,
+ size_type n2) const {
+ return substr(pos1, n1).compare(basic_string_view(s, n2));
+ }
+
+ private:
+ const_pointer data_;
+ size_type size_;
+};
+
+/**
+ * \brief Equality operator.
+ * \returns <tt>lhs.compare(rhs) == 0</tt>.
+ */
+template <class charT, class traits>
+constexpr bool operator==(basic_string_view<charT, traits> lhs,
+ basic_string_view<charT, traits> rhs) noexcept {
+ return lhs.compare(rhs) == 0;
+}
+
+/**
+ * \brief Inequality operator.
+ * \returns <tt>!(lhs == rhs)</tt>.
+ */
+template <class charT, class traits>
+constexpr bool operator!=(basic_string_view<charT, traits> lhs,
+ basic_string_view<charT, traits> rhs) noexcept {
+ return !(lhs == rhs);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>lhs.compare(rhs) < 0</tt>.
+ */
+template <class charT, class traits>
+constexpr bool operator<(basic_string_view<charT, traits> lhs,
+ basic_string_view<charT, traits> rhs) noexcept {
+ return lhs.compare(rhs) < 0;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>rhs < lhs</tt>.
+ */
+template <class charT, class traits>
+constexpr bool operator>(basic_string_view<charT, traits> lhs,
+ basic_string_view<charT, traits> rhs) noexcept {
+ return rhs < lhs;
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(lhs > rhs)</tt>.
+ */
+template <class charT, class traits>
+constexpr bool operator<=(basic_string_view<charT, traits> lhs,
+ basic_string_view<charT, traits> rhs) noexcept {
+ return !(lhs > rhs);
+}
+
+/**
+ * \brief Comparison operator.
+ * \returns <tt>!(lhs < rhs)</tt>.
+ */
+template <class charT, class traits>
+constexpr bool operator>=(basic_string_view<charT, traits> lhs,
+ basic_string_view<charT, traits> rhs) noexcept {
+ return !(lhs < rhs);
+}
+
+/**
+ * \brief Output stream operator.
+ */
+template <class charT, class traits>
+std::basic_ostream<charT, traits>& operator<<(
+ std::basic_ostream<charT, traits>& os,
+ basic_string_view<charT, traits> str) {
+ return os << str.to_string();
+}
+
+typedef basic_string_view<char> string_view;
+} // namespace network
+
+#endif // NETWORK_STRING_VIEW_INC
diff --git a/graphics/asymptote/LspCpp/network/uri.hpp b/graphics/asymptote/LspCpp/network/uri.hpp
new file mode 100644
index 0000000000..f3d86e09ec
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri.hpp
@@ -0,0 +1,38 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Copyright 2012 Dean Michael Berris <dberris@google.com>
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_HPP
+#define NETWORK_URI_HPP
+
+/**
+ * \defgroup uri URI
+ *
+ * This module contains a class encapsulating a URI, a URI builder and
+ * percent encoding and decoding functions.
+ *
+ * \defgroup optional Optional
+ *
+ * This module contains a utility to represent optional values.
+ *
+ * \defgroup string String
+ *
+ * This module contains a class for a non-owning reference to a string.
+ *
+ * \namespace network
+ *
+ * The \c network namespace contains all the classes and functions for
+ * the URI in this library.
+ *
+ * \file
+ * \brief Contains the uri, uri_builder classes and functions
+ * for percent encoding and decoding.
+ */
+
+#include <network/uri/uri.hpp>
+#include <network/uri/uri_io.hpp>
+
+#endif // NETWORK_URI_HPP
diff --git a/graphics/asymptote/LspCpp/network/uri/config.hpp b/graphics/asymptote/LspCpp/network/uri/config.hpp
new file mode 100644
index 0000000000..39c3b58c28
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/config.hpp
@@ -0,0 +1,20 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Copyright 2012 Dean Michael Berris <dberris@google.com>
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file
+ * \brief Contains macros to configure compiler or platform-specific workarounds.
+ */
+
+#ifndef NETWORK_URI_CONFIG_INC
+#define NETWORK_URI_CONFIG_INC
+
+#ifdef _MSC_VER
+#define NETWORK_URI_MSVC _MSC_VER
+#endif // _MSC_VER
+
+#endif // NETWORK_URI_CONFIG_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/algorithm.hpp b/graphics/asymptote/LspCpp/network/uri/detail/algorithm.hpp
new file mode 100644
index 0000000000..2358af9a04
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/algorithm.hpp
@@ -0,0 +1,73 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_RANGE_INC
+#define NETWORK_DETAIL_RANGE_INC
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+#include <string>
+#include <cctype>
+#include <locale>
+
+namespace network {
+namespace detail {
+template <class Rng, class Pred>
+inline void for_each(Rng& rng, Pred&& pred) {
+ std::for_each(std::begin(rng), std::end(rng), pred);
+}
+
+template <class Rng, class Iter, class Pred>
+inline void transform(Rng& rng, Iter out, Pred&& pred) {
+ std::transform(std::begin(rng), std::end(rng), out, pred);
+}
+
+template <class Rng>
+inline typename Rng::difference_type distance(Rng& rng) {
+ return std::distance(std::begin(rng), std::end(rng));
+}
+
+template <class Rng1, class Rng2>
+inline bool equal(const Rng1& rng1, const Rng2& rng2) {
+ return std::equal(std::begin(rng1), std::end(rng1), std::begin(rng2));
+}
+
+template <class Rng, class Pred>
+inline void remove_erase_if(Rng& rng, Pred&& pred) {
+ auto first = std::begin(rng), last = std::end(rng);
+ auto it = std::remove_if(first, last, pred);
+ rng.erase(it, last);
+}
+
+inline std::string trim_front(const std::string& str) {
+ auto first = std::begin(str), last = std::end(str);
+ auto it = std::find_if(first, last, [](char ch) {
+ return !std::isspace(ch, std::locale());
+ });
+ return std::string(it, last);
+}
+
+inline std::string trim_back(const std::string& str) {
+ using reverse_iterator = std::reverse_iterator<std::string::const_iterator>;
+
+ auto first = reverse_iterator(std::end(str)),
+ last = reverse_iterator(std::begin(str));
+ auto it = std::find_if(first, last, [](char ch) {
+ return !std::isspace(ch, std::locale());
+ });
+ std::string result(it, last);
+ std::reverse(std::begin(result), std::end(result));
+ return result;
+}
+
+inline
+std::string trim_copy(const std::string &str) {
+ return trim_back(trim_front(str));
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_RANGE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/decode.hpp b/graphics/asymptote/LspCpp/network/uri/detail/decode.hpp
new file mode 100644
index 0000000000..9d0aaaa1b5
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/decode.hpp
@@ -0,0 +1,78 @@
+// Copyright (c) Glyn Matthews 2011-2016.
+// Copyright 2012 Dean Michael Berris <dberris@google.com>
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_DECODE_INC
+#define NETWORK_URI_DECODE_INC
+
+#include <network/uri/uri_errors.hpp>
+#include <iterator>
+#include <cassert>
+
+namespace network {
+namespace detail {
+template <typename CharT>
+CharT letter_to_hex(CharT in) {
+ if ((in >= '0') && (in <= '9')) {
+ return in - '0';
+ }
+
+ if ((in >= 'a') && (in <= 'f')) {
+ return in + 10 - 'a';
+ }
+
+ if ((in >= 'A') && (in <= 'F')) {
+ return in + 10 - 'A';
+ }
+
+ throw percent_decoding_error(uri_error::non_hex_input);
+}
+
+template <class InputIterator, class charT>
+InputIterator decode_char(InputIterator it, charT *out) {
+ assert(*it == '%');
+ ++it;
+ auto h0 = *it;
+ auto v0 = detail::letter_to_hex(h0);
+ ++it;
+ auto h1 = *it;
+ auto v1 = detail::letter_to_hex(h1);
+ ++it;
+ *out = static_cast<charT>((0x10 * v0) + v1);
+ return it;
+}
+
+template <class InputIterator, class OutputIterator>
+OutputIterator decode(InputIterator in_begin, InputIterator in_end,
+ OutputIterator out_begin) {
+ auto it = in_begin;
+ auto out = out_begin;
+ while (it != in_end) {
+ if (*it == '%') {
+ if (std::distance(it, in_end) < 3) {
+ throw percent_decoding_error(uri_error::not_enough_input);
+ }
+ char c = '\0';
+ it = decode_char(it, &c);
+ *out = c;
+ ++out;
+ } else {
+ *out++ = *it++;
+ }
+ }
+ return out;
+}
+
+template <class String>
+String decode(const String &source) {
+ String unencoded;
+ decode(std::begin(source), std::end(source), std::back_inserter(unencoded));
+ return unencoded;
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_URI_DECODE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/encode.hpp b/graphics/asymptote/LspCpp/network/uri/detail/encode.hpp
new file mode 100644
index 0000000000..be1dec9fd1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/encode.hpp
@@ -0,0 +1,169 @@
+// Copyright (c) Glyn Matthews 2011-2016.
+// Copyright 2012 Dean Michael Berris <dberris@google.com>
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_ENCODE_INC
+#define NETWORK_URI_ENCODE_INC
+
+#include <network/uri/uri_errors.hpp>
+#include <iterator>
+#include <cstring>
+#include <cassert>
+#include <algorithm>
+
+namespace network {
+namespace detail {
+template <typename CharT>
+inline CharT hex_to_letter(CharT in) {
+ if ((in >= 0) && (in < 10)) {
+ return in + '0';
+ }
+
+ if ((in >= 10) && (in < 16)) {
+ return in - 10 + 'A';
+ }
+
+ return in;
+}
+
+template <class charT, class OutputIterator>
+void percent_encode(charT in, OutputIterator &out) {
+ out++ = '%';
+ out++ = hex_to_letter((in >> 4) & 0x0f);
+ out++ = hex_to_letter(in & 0x0f);
+}
+
+template <class charT>
+bool is_unreserved(charT in) {
+ return ((in >= 'a') && (in <= 'z')) ||
+ ((in >= 'A') && (in <= 'Z')) ||
+ ((in >= '0') && (in <= '9')) ||
+ (in == '-') ||
+ (in == '.') ||
+ (in == '_') ||
+ (in == '~');
+}
+
+template <class charT, class OutputIterator>
+void encode_char(charT in, OutputIterator &out, const char *ignore = "") {
+ if (is_unreserved(in)) {
+ out++ = in;
+ } else {
+ auto first = ignore, last = ignore + std::strlen(ignore);
+ if (std::find(first, last, in) != last) {
+ out++ = in;
+ } else {
+ percent_encode(in, out);
+ }
+ }
+}
+
+template <typename InputIterator, typename OutputIterator>
+OutputIterator encode_user_info(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, ":");
+ ++it;
+ }
+ return out;
+}
+
+template <typename InputIterator, typename OutputIterator>
+OutputIterator encode_host(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "[:]");
+ ++it;
+ }
+ return out;
+}
+
+template <typename InputIterator, typename OutputIterator>
+OutputIterator encode_port(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out);
+ ++it;
+ }
+ return out;
+}
+
+template <typename InputIterator, typename OutputIterator>
+OutputIterator encode_path(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "/.@%;=");
+ ++it;
+ }
+ return out;
+}
+
+template <typename InputIterator, typename OutputIterator>
+OutputIterator encode_query_component(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "/?");
+ ++it;
+ }
+ return out;
+}
+
+template <typename InputIterator, typename OutputIterator>
+OutputIterator encode_fragment(InputIterator first, InputIterator last,
+ OutputIterator out) {
+ auto it = first;
+ while (it != last) {
+ detail::encode_char(*it, out, "/.@&l;=%");
+ ++it;
+ }
+ return out;
+}
+
+template <class String>
+String encode_user_info(const String &user_info) {
+ String encoded;
+ encode_user_info(std::begin(user_info), std::end(user_info),
+ std::back_inserter(encoded));
+ return encoded;
+}
+
+template <class String>
+String encode_host(const String &host) {
+ String encoded;
+ encode_host(std::begin(host), std::end(host), std::back_inserter(encoded));
+ return encoded;
+}
+
+template <class String>
+String encode_port(const String &port) {
+ String encoded;
+ encode_port(std::begin(port), std::end(port), std::back_inserter(encoded));
+ return encoded;
+}
+
+template <class String>
+String encode_path(const String &path) {
+ String encoded;
+ encode_path(std::begin(path), std::end(path), std::back_inserter(encoded));
+ return encoded;
+}
+
+template <class String>
+String encode_fragment(const String &fragment) {
+ String encoded;
+ encode_fragment(std::begin(fragment), std::end(fragment),
+ std::back_inserter(encoded));
+ return encoded;
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_URI_ENCODE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/grammar.hpp b/graphics/asymptote/LspCpp/network/uri/detail/grammar.hpp
new file mode 100644
index 0000000000..7e4a9fe3b8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/grammar.hpp
@@ -0,0 +1,130 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_GRAMMAR_INC
+#define NETWORK_DETAIL_URI_GRAMMAR_INC
+
+#include <network/string_view.hpp>
+#include <cstdlib>
+#include <locale>
+#include <cstring>
+#include <string>
+
+namespace network {
+namespace detail {
+inline bool isalnum(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ if (it != last) {
+ if (std::isalnum(*it, std::locale::classic())) {
+ ++it;
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool isdigit(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ if (it != last) {
+ if (std::isdigit(*it, std::locale::classic())) {
+ ++it;
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool is_in(string_view::const_iterator &it,
+ string_view::const_iterator last, const char *chars) {
+ if (it != last) {
+ auto length = std::strlen(chars);
+ for (std::size_t i = 0; i < length; ++i) {
+ if (*it == chars[i]) {
+ ++it;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+inline bool is_sub_delim(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ return is_in(it, last, "!$&'()*+,;=");
+}
+
+inline bool is_ucschar(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ if (it == last) {
+ return false;
+ }
+
+
+
+ return false;
+}
+
+inline bool is_private(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ return false;
+}
+
+inline bool is_unreserved(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ return isalnum(it, last) || is_in(it, last, "-._~");
+}
+
+inline bool is_pct_encoded(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ if (it == last) {
+ return false;
+ }
+
+ string_view::const_iterator it_copy = it;
+
+ if (*it_copy == '%') {
+ ++it_copy;
+ if (it_copy == last) {
+ return false;
+ }
+ }
+
+ if (std::isxdigit(*it_copy, std::locale::classic())) {
+ ++it_copy;
+ if (it_copy == last) {
+ return false;
+ }
+ }
+
+ if (std::isxdigit(*it_copy, std::locale::classic())) {
+ ++it_copy;
+ it = it_copy;
+ return true;
+ }
+
+ return false;
+}
+
+inline bool is_pchar(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ return
+ is_unreserved(it, last) ||
+ is_pct_encoded(it, last) ||
+ is_sub_delim(it, last) ||
+ is_in(it, last, ":@") ||
+ is_ucschar(it, last)
+ ;
+}
+
+inline bool is_valid_port(string_view::const_iterator it) {
+ const char* port_first = &(*it);
+ char* port_last = 0;
+ unsigned long value = std::strtoul(port_first, &port_last, 10);
+ return (value < std::numeric_limits<unsigned short>::max());
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_GRAMMAR_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/translate.hpp b/graphics/asymptote/LspCpp/network/uri/detail/translate.hpp
new file mode 100644
index 0000000000..7566c258e1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/translate.hpp
@@ -0,0 +1,89 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_DETAIL_TRANSLATE_INC
+#define NETWORK_URI_DETAIL_TRANSLATE_INC
+
+#include <string>
+
+namespace network {
+namespace detail {
+template <typename Source>
+struct translate_impl;
+
+template <>
+struct translate_impl<std::string> {
+ std::string operator()(const std::string &source) const { return source; }
+};
+
+template <int N>
+struct translate_impl<char[N]> {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <>
+struct translate_impl<char *> {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <>
+struct translate_impl<const char *> {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <int N>
+struct translate_impl<const char[N]> {
+ std::string operator()(const char *source) const { return source; }
+};
+
+template <>
+struct translate_impl<std::wstring> {
+ std::string operator()(const std::wstring &source) const {
+ return std::string(std::begin(source), std::end(source));
+ }
+};
+
+template <int N>
+struct translate_impl<const wchar_t[N]> {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl<std::wstring> impl;
+ return impl(source);
+ }
+};
+
+template <int N>
+struct translate_impl<wchar_t[N]> {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl<std::wstring> impl;
+ return impl(source);
+ }
+};
+
+template <>
+struct translate_impl<wchar_t *> {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl<std::wstring> impl;
+ return impl(source);
+ }
+};
+
+template <>
+struct translate_impl<const wchar_t *> {
+ std::string operator()(const wchar_t *source) const {
+ translate_impl<std::wstring> impl;
+ return impl(source);
+ }
+};
+
+template <typename Source>
+inline std::string translate(const Source &source) {
+ translate_impl<Source> impl;
+ return impl(source);
+}
+
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_URI_DETAIL_TRANSLATE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.cpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.cpp
new file mode 100644
index 0000000000..6eec782c82
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.cpp
@@ -0,0 +1,76 @@
+// Copyright 2016-2017 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "uri_advance_parts.hpp"
+#include <iterator>
+#include <utility>
+#include <limits>
+
+namespace network {
+namespace detail {
+namespace {
+template <class Iterator>
+uri_part copy_part(Iterator first, Iterator last,
+ string_view::const_iterator &it) {
+ auto part_first = it;
+ std::advance(it, std::distance(first, last));
+ return detail::uri_part(part_first, it);
+}
+} // namespace
+
+uri_part copy_part(const std::string &uri, string_view::const_iterator &it) {
+ return copy_part(std::begin(uri), std::end(uri), it);
+}
+
+void advance_parts(string_view uri_view, uri_parts &parts,
+ const uri_parts &existing_parts) {
+ auto first = std::begin(uri_view);
+
+ auto it = first;
+ if (auto scheme = existing_parts.scheme) {
+ parts.scheme = copy_part(std::begin(*scheme), std::end(*scheme), it);
+
+ // ignore : for all URIs
+ if (*it == ':') {
+ ++it;
+ }
+
+ // ignore // for hierarchical URIs
+ if (existing_parts.hier_part.host) {
+ std::advance(it, 2);
+ }
+ }
+
+ if (auto user_info = existing_parts.hier_part.user_info) {
+ parts.hier_part.user_info =
+ copy_part(std::begin(*user_info), std::end(*user_info), it);
+ ++it; // ignore @
+ }
+
+ if (auto host = existing_parts.hier_part.host) {
+ parts.hier_part.host = copy_part(std::begin(*host), std::end(*host), it);
+ }
+
+ if (auto port = existing_parts.hier_part.port) {
+ ++it; // ignore :
+ parts.hier_part.port = copy_part(std::begin(*port), std::end(*port), it);
+ }
+
+ if (auto path = existing_parts.hier_part.path) {
+ parts.hier_part.path = copy_part(std::begin(*path), std::end(*path), it);
+ }
+
+ if (auto query = existing_parts.query) {
+ ++it; // ignore ?
+ parts.query = copy_part(std::begin(*query), std::end(*query), it);
+ }
+
+ if (auto fragment = existing_parts.fragment) {
+ ++it; // ignore #
+ parts.fragment = copy_part(std::begin(*fragment), std::end(*fragment), it);
+ }
+}
+} // namespace detail
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.hpp
new file mode 100644
index 0000000000..4d9fd76768
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_advance_parts.hpp
@@ -0,0 +1,21 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_ADVANCE_INC
+#define NETWORK_DETAIL_URI_ADVANCE_INC
+
+#include <network/uri/detail/uri_parts.hpp>
+
+namespace network {
+namespace detail {
+uri_part copy_part(const std::string &part,
+ string_view::const_iterator &it);
+
+void advance_parts(string_view uri_view, uri_parts &parts,
+ const uri_parts &existing_parts);
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_ADVANCE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.cpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.cpp
new file mode 100644
index 0000000000..1c6ca1484b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.cpp
@@ -0,0 +1,87 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iterator>
+#include <vector>
+#include <algorithm>
+
+#ifdef NETWORK_URI_EXTERNAL_BOOST
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/join.hpp>
+namespace boost = boost;
+#else // NETWORK_URI_EXTERNAL_BOOST
+#include "boost/algorithm/string/split.hpp"
+#include "boost/algorithm/string/join.hpp"
+#endif // NETWORK_URI_EXTERNAL_BOOST
+
+#include "uri_normalize.hpp"
+#include "uri_percent_encode.hpp"
+#include "algorithm.hpp"
+
+namespace network {
+namespace detail {
+std::string normalize_path_segments(string_view path) {
+ std::string result;
+
+ if (!path.empty()) {
+ std::vector<std::string> path_segments;
+ boost::split(path_segments, path, [](char ch) {
+ return ch == '/';
+ });
+
+ bool last_segment_is_slash = path_segments.back().empty();
+ std::vector<std::string> normalized_segments;
+ for (const auto &segment : path_segments) {
+ if (segment.empty() || (segment == ".")) {
+ continue;
+ }
+ else if (segment == "..") {
+ if (normalized_segments.empty()) {
+ throw uri_builder_error();
+ }
+ normalized_segments.pop_back();
+ }
+ else {
+ normalized_segments.push_back(segment);
+ }
+ }
+
+ for (const auto &segment : normalized_segments) {
+ result += "/" + segment;
+ }
+
+ if (last_segment_is_slash) {
+ result += "/";
+ }
+ }
+
+ if (result.empty()) {
+ result = "/";
+ }
+
+ return result;
+}
+
+std::string normalize_path(string_view path, uri_comparison_level level) {
+ auto result = path.to_string();
+
+ if (uri_comparison_level::syntax_based == level) {
+ // case normalization
+ detail::for_each(result, percent_encoded_to_upper<std::string>());
+
+ // % encoding normalization
+ result.erase(
+ detail::decode_encoded_unreserved_chars(std::begin(result),
+ std::end(result)),
+ std::end(result));
+
+ // % path segment normalization
+ result = normalize_path_segments(result);
+ }
+
+ return result;
+}
+} // namespace detail
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.hpp
new file mode 100644
index 0000000000..3c2e03b11d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_normalize.hpp
@@ -0,0 +1,20 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_NORMALIZE_INC
+#define NETWORK_DETAIL_NORMALIZE_INC
+
+#include <network/uri/uri.hpp>
+#include <network/string_view.hpp>
+
+namespace network {
+namespace detail {
+std::string normalize_path_segments(string_view path);
+
+std::string normalize_path(string_view path, uri_comparison_level level);
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_NORMALIZE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_parse.cpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse.cpp
new file mode 100644
index 0000000000..46dd1b0f26
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse.cpp
@@ -0,0 +1,424 @@
+// Copyright 2016-2017 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "uri_parse.hpp"
+#include <iterator>
+#include <limits>
+#include "grammar.hpp"
+#include <network/uri/detail/uri_parts.hpp>
+
+namespace network {
+namespace detail {
+namespace {
+enum class uri_state {
+ scheme,
+ hier_part,
+ query,
+ fragment
+};
+
+enum class hier_part_state {
+ first_slash,
+ second_slash,
+ authority,
+ host,
+ host_ipv6,
+ port,
+ path
+};
+
+bool validate_scheme(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ if (it == last) {
+ return false;
+ }
+
+ // The first character must be a letter
+ if (!std::isalpha(*it, std::locale("C"))) {
+ return false;
+ }
+ ++it;
+
+ while (it != last) {
+ if (*it == ':') {
+ break;
+ }
+ else if (!isalnum(it, last) && !is_in(it, last, "+-.")) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool validate_user_info(string_view::const_iterator it,
+ string_view::const_iterator last) {
+ while (it != last) {
+ if (!is_unreserved(it, last) &&
+ !is_pct_encoded(it, last) &&
+ !is_sub_delim(it, last) &&
+ !is_in(it, last, ":")) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool set_host_and_port(string_view::const_iterator first,
+ string_view::const_iterator last,
+ string_view::const_iterator last_colon,
+ uri_parts &parts) {
+ if (first >= last_colon) {
+ parts.hier_part.host = uri_part(first, last);
+ }
+ else {
+ auto port_start = last_colon;
+ ++port_start;
+ parts.hier_part.host = uri_part(first, last_colon);
+ if (!is_valid_port(port_start)) {
+ return false;
+ }
+ parts.hier_part.port = uri_part(port_start, last);
+ }
+ return true;
+}
+
+bool validate_fragment(string_view::const_iterator &it,
+ string_view::const_iterator last) {
+ while (it != last) {
+ if (!is_pchar(it, last) && !is_in(it, last, "?/")) {
+ return false;
+ }
+ }
+ return true;
+}
+} // namespace
+
+bool parse(string_view::const_iterator &it, string_view::const_iterator last,
+ uri_parts &parts) {
+ auto state = uri_state::scheme;
+
+ auto first = it;
+
+ if (it == last) {
+ return false;
+ }
+
+ if (validate_scheme(it, last)) {
+ parts.scheme = uri_part(first, it);
+ // move past the scheme delimiter
+ ++it;
+ state = uri_state::hier_part;
+ }
+ else {
+ return false;
+ }
+
+ // Hierarchical part
+ auto hp_state = hier_part_state::first_slash;
+ // this is used by the user_info/port
+ auto last_colon = first;
+ while (it != last) {
+ if (hp_state == hier_part_state::first_slash) {
+ if (*it == '/') {
+ hp_state = hier_part_state::second_slash;
+ // set the first iterator in case the second slash is not forthcoming
+ first = it;
+ ++it;
+ continue;
+ }
+ else {
+ hp_state = hier_part_state::path;
+ first = it;
+ }
+ }
+ else if (hp_state == hier_part_state::second_slash) {
+ if (*it == '/') {
+ hp_state = hier_part_state::authority;
+ ++it;
+ first = it;
+ continue;
+ }
+ else {
+ // it's a valid URI, and this is the beginning of the path
+ hp_state = hier_part_state::path;
+ }
+ }
+ else if (hp_state == hier_part_state::authority) {
+ if (is_in(first, last, "@:")) {
+ return false;
+ }
+
+ // reset the last colon
+ if (first == it) {
+ last_colon = first;
+ }
+
+ if (*it == '@') {
+ if (!validate_user_info(first, it)) {
+ return false;
+ }
+ parts.hier_part.user_info = uri_part(first, it);
+ hp_state = hier_part_state::host;
+ ++it;
+ first = it;
+
+ if (*first == '[') {
+ // this is an IPv6 address
+ hp_state = hier_part_state::host_ipv6;
+ }
+
+ continue;
+ }
+ else if (*it == '[') {
+ // this is an IPv6 address
+ hp_state = hier_part_state::host_ipv6;
+ first = it;
+ continue;
+ }
+ else if (*it == ':') {
+ last_colon = it;
+ }
+ else if (*it == '/') {
+ // we skipped right past the host and port, and are at the path.
+ if (!set_host_and_port(first, it, last_colon, parts)) {
+ return false;
+ }
+ hp_state = hier_part_state::path;
+ first = it;
+ continue;
+ }
+ else if (*it == '?') {
+ // the path is empty, but valid, and the next part is the query
+ if (!set_host_and_port(first, it, last_colon, parts)) {
+ return false;
+ }
+ parts.hier_part.path = uri_part(it, it);
+ state = uri_state::query;
+ ++it;
+ first = it;
+ break;
+ }
+ else if (*it == '#') {
+ // the path is empty, but valid, and the next part is the fragment
+ if (!set_host_and_port(first, it, last_colon, parts)) {
+ return false;
+ }
+ parts.hier_part.path = uri_part(it, it);
+ state = uri_state::fragment;
+ ++it;
+ first = it;
+ break;
+ }
+ }
+ else if (hp_state == hier_part_state::host) {
+ if (*first == ':') {
+ return false;
+ }
+
+ if (*it == ':') {
+ parts.hier_part.host = uri_part(first, it);
+ hp_state = hier_part_state::port;
+ ++it;
+ first = it;
+ continue;
+ }
+ else if (*it == '/') {
+ parts.hier_part.host = uri_part(first, it);
+ hp_state = hier_part_state::path;
+ first = it;
+ continue;
+ }
+ else if (*it == '?') {
+ // the path is empty, but valid, and the next part is the query
+ parts.hier_part.host = uri_part(first, it);
+ parts.hier_part.path = uri_part(it, it);
+ state = uri_state::query;
+ ++it;
+ first = it;
+ break;
+ }
+ else if (*it == '#') {
+ // the path is empty, but valid, and the next part is the fragment
+ parts.hier_part.host = uri_part(first, it);
+ parts.hier_part.path = uri_part(it, it);
+ state = uri_state::fragment;
+ ++it;
+ first = it;
+ break;
+ }
+ }
+ else if (hp_state == hier_part_state::host_ipv6) {
+ if (*first != '[') {
+ return false;
+ }
+
+ if (*it == ']') {
+ ++it;
+ // Then test if the next part is a host, part, or the end of the file
+ if (it == last) {
+ break;
+ }
+ else if (*it == ':') {
+ parts.hier_part.host = uri_part(first, it);
+ hp_state = hier_part_state::port;
+ ++it;
+ first = it;
+ }
+ else if (*it == '/') {
+ parts.hier_part.host = uri_part(first, it);
+ hp_state = hier_part_state::path;
+ first = it;
+ }
+ else if (*it == '?') {
+ parts.hier_part.host = uri_part(first, it);
+ parts.hier_part.path = uri_part(it, it);
+ state = uri_state::query;
+ ++it;
+ first = it;
+ break;
+ }
+ else if (*it == '#') {
+ parts.hier_part.host = uri_part(first, it);
+ parts.hier_part.path = uri_part(it, it);
+ state = uri_state::fragment;
+ ++it;
+ first = it;
+ break;
+ }
+ continue;
+ }
+ }
+ else if (hp_state == hier_part_state::port) {
+ if (*first == '/') {
+ // the port is empty, but valid
+ if (!is_valid_port(first)) {
+ return false;
+ }
+ parts.hier_part.port = uri_part(first, it);
+
+ // the port isn't set, but the path is
+ hp_state = hier_part_state::path;
+ continue;
+ }
+
+ if (*it == '/') {
+ if (!is_valid_port(first)) {
+ return false;
+ }
+ parts.hier_part.port = uri_part(first, it);
+ hp_state = hier_part_state::path;
+ first = it;
+ continue;
+ }
+ else if (!isdigit(it, last)) {
+ return false;
+ }
+ continue;
+ }
+ else if (hp_state == hier_part_state::path) {
+ if (*it == '?') {
+ parts.hier_part.path = uri_part(first, it);
+ // move past the query delimiter
+ ++it;
+ first = it;
+ state = uri_state::query;
+ break;
+ }
+ else if (*it == '#') {
+ parts.hier_part.path = uri_part(first, it);
+ // move past the fragment delimiter
+ ++it;
+ first = it;
+ state = uri_state::fragment;
+ break;
+ }
+
+ if (!is_pchar(it, last) && !is_in(it, last, "/")) {
+ return false;
+ }
+ else {
+ continue;
+ }
+ }
+
+ ++it;
+ }
+
+ if (state == uri_state::query) {
+ while (it != last) {
+ if (!is_pchar(it, last) && !is_in(it, last, "?/")) {
+ // If this is a fragment, keep going
+ if (*it == '#') {
+ parts.query = uri_part(first, it);
+ // move past the fragment delimiter
+ ++it;
+ first = it;
+ state = uri_state::fragment;
+ break;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ }
+
+ if (state == uri_state::fragment) {
+ if (!validate_fragment(it, last)) {
+ return false;
+ }
+ }
+
+ // we're done!
+ if (state == uri_state::hier_part) {
+ if (hp_state == hier_part_state::authority) {
+ if (first == last) {
+ return false;
+ }
+
+ if (!set_host_and_port(first, last, last_colon, parts)) {
+ return false;
+ }
+ parts.hier_part.path = uri_part(last, last);
+ }
+ else if (hp_state == hier_part_state::host) {
+ if (first == last) {
+ return false;
+ }
+
+ if (!set_host_and_port(first, last, last_colon, parts)) {
+ return false;
+ }
+ parts.hier_part.path = uri_part(last, last);
+ }
+ else if (hp_state == hier_part_state::host_ipv6) {
+ if (!set_host_and_port(first, last, last_colon, parts)) {
+ return false;
+ }
+ parts.hier_part.path = uri_part(last, last);
+ }
+ else if (hp_state == hier_part_state::port) {
+ if (!is_valid_port(first)) {
+ return false;
+ }
+ parts.hier_part.port = uri_part(first, last);
+ parts.hier_part.path = uri_part(last, last);
+ }
+ else if (hp_state == hier_part_state::path) {
+ parts.hier_part.path = uri_part(first, last);
+ }
+ }
+ else if (state == uri_state::query) {
+ parts.query = uri_part(first, last);
+ }
+ else if (state == uri_state::fragment) {
+ parts.fragment = uri_part(first, last);
+ }
+
+ return true;
+}
+} // namespace detail
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_parse.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse.hpp
new file mode 100644
index 0000000000..73835c3656
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse.hpp
@@ -0,0 +1,19 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_PARSE_INC
+#define NETWORK_DETAIL_URI_PARSE_INC
+
+#include <network/string_view.hpp>
+
+namespace network {
+namespace detail {
+struct uri_parts;
+
+bool parse(string_view::const_iterator &first, string_view::const_iterator last, uri_parts &parts);
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_PARSE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.cpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.cpp
new file mode 100644
index 0000000000..0db307f1f6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.cpp
@@ -0,0 +1,130 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "uri_parse_authority.hpp"
+#include <cstdlib>
+#include <iterator>
+#include <limits>
+#include "grammar.hpp"
+
+namespace network {
+namespace detail {
+namespace {
+enum class authority_state {
+ user_info,
+ host,
+ host_ipv6,
+ port
+};
+} // namespace
+
+bool parse_authority(string_view::const_iterator &it,
+ string_view::const_iterator last,
+ optional<uri_part> &user_info,
+ optional<uri_part> &host,
+ optional<uri_part> &port) {
+ auto first = it;
+
+ auto state = authority_state::user_info;
+ while (it != last) {
+ if (state == authority_state::user_info) {
+ if (is_in(first, last, "@:")) {
+ return false;
+ }
+
+ if (*it == '@') {
+ user_info = uri_part(first, it);
+ state = authority_state::host;
+ ++it;
+ first = it;
+ continue;
+ }
+ else if (*it == '[') {
+ // this is an IPv6 address
+ state = authority_state::host_ipv6;
+ first = it;
+ continue;
+ }
+ else if (*it == ':') {
+ // this is actually the host, and the next part is expected to be the port
+ host = uri_part(first, it);
+ state = authority_state::port;
+ ++it;
+ first = it;
+ continue;
+ }
+ }
+ else if (state == authority_state::host) {
+ if (*first == ':') {
+ return false;
+ }
+
+ if (*it == ':') {
+ host = uri_part(first, it);
+ state = authority_state::port;
+ ++it;
+ first = it;
+ continue;
+ }
+ }
+ else if (state == authority_state::host_ipv6) {
+ if (*first != '[') {
+ return false;
+ }
+
+ if (*it == ']') {
+ host = uri_part(first, it);
+ ++it;
+ // Then test if the next part is a host, part, or the end of the file
+ if (it == last) {
+ break;
+ }
+ else if (*it == ':') {
+ host = uri_part(first, it);
+ state = authority_state::port;
+ ++it;
+ first = it;
+ }
+ }
+ }
+ else if (state == authority_state::port) {
+ if (*first == '/') {
+ // the port is empty, but valid
+ port = uri_part(first, it);
+ if (!is_valid_port(std::begin(*port))) {
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!isdigit(it, last)) {
+ return false;
+ }
+ }
+
+ ++it;
+ }
+
+ if (state == authority_state::user_info) {
+ host = uri_part(first, last);
+ }
+ else if (state == authority_state::host) {
+ host = uri_part(first, last);
+ }
+ else if (state == authority_state::host_ipv6) {
+ host = uri_part(first, last);
+ }
+ else if (state == authority_state::port) {
+ port = uri_part(first, last);
+ if (!is_valid_port(std::begin(*port))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+} // namespace detail
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.hpp
new file mode 100644
index 0000000000..cb37104258
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_parse_authority.hpp
@@ -0,0 +1,21 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_PARSE_AUTHORITY_INC
+#define NETWORK_DETAIL_URI_PARSE_AUTHORITY_INC
+
+#include <network/uri/detail/uri_parts.hpp>
+
+namespace network {
+namespace detail {
+bool parse_authority(string_view::const_iterator &first,
+ string_view::const_iterator last,
+ optional<uri_part> &user_info,
+ optional<uri_part> &host,
+ optional<uri_part> &port);
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_PARSE_AUTHORITY_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_parts.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_parts.hpp
new file mode 100644
index 0000000000..17a69687fe
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_parts.hpp
@@ -0,0 +1,88 @@
+// Copyright 2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_PARTS_INC
+#define NETWORK_DETAIL_URI_PARTS_INC
+
+#include <string>
+#include <utility>
+#include <iterator>
+#include <network/optional.hpp>
+#include <network/string_view.hpp>
+
+namespace network {
+namespace detail {
+class uri_part {
+ public:
+ typedef string_view::value_type value_type;
+ typedef string_view::iterator iterator;
+ typedef string_view::const_iterator const_iterator;
+ typedef string_view::const_pointer const_pointer;
+ typedef string_view::size_type size_type;
+ typedef string_view::difference_type difference_type;
+
+ uri_part() noexcept = default;
+
+ uri_part(const_iterator first, const_iterator last) noexcept
+ : first(first), last(last) {}
+
+ const_iterator begin() const noexcept { return first; }
+
+ const_iterator end() const noexcept { return last; }
+
+ bool empty() const noexcept { return first == last; }
+
+ std::string to_string() const { return std::string(first, last); }
+
+ const_pointer ptr() const noexcept {
+ assert(first != last);
+ return first;
+ }
+
+ difference_type length() const noexcept {
+ return last - first;
+ }
+
+ string_view to_string_view() const noexcept { return string_view(ptr(), length()); }
+
+ private:
+ const_iterator first, last;
+};
+
+struct hierarchical_part {
+ hierarchical_part() = default;
+
+ optional<uri_part> user_info;
+ optional<uri_part> host;
+ optional<uri_part> port;
+ optional<uri_part> path;
+
+ void clear() {
+ user_info = nullopt;
+ host = nullopt;
+ port = nullopt;
+ path = nullopt;
+ }
+};
+
+struct uri_parts {
+ uri_parts() = default;
+
+ optional<uri_part> scheme;
+ hierarchical_part hier_part;
+ optional<uri_part> query;
+ optional<uri_part> fragment;
+
+ void clear() {
+ scheme = nullopt;
+ hier_part.clear();
+ query = nullopt;
+ fragment = nullopt;
+ }
+};
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_PARTS_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_percent_encode.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_percent_encode.hpp
new file mode 100644
index 0000000000..ab5134db9c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_percent_encode.hpp
@@ -0,0 +1,80 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_URI_PERCENT_ENCODE_INC
+#define NETWORK_DETAIL_URI_PERCENT_ENCODE_INC
+
+#include <string>
+#include <vector>
+#include <locale>
+#include <network/optional.hpp>
+#include <network/uri/detail/decode.hpp>
+
+namespace network {
+namespace detail {
+
+inline optional<char> percent_encode(std::string::const_iterator it) {
+ try {
+ char output = '\0';
+ detail::decode_char(it, &output);
+ return output;
+ } catch (percent_decoding_error &) {
+ return optional<char>();
+ }
+}
+
+template <class String>
+struct percent_encoded_to_upper {
+ percent_encoded_to_upper() : count(0) {}
+
+ void operator()(typename String::value_type &c) {
+ if (c == '%') {
+ count = 2;
+ } else if (count > 0) {
+ c = std::toupper(c, std::locale());
+ --count;
+ }
+ }
+
+ unsigned count;
+};
+
+template <class Iter>
+Iter decode_encoded_unreserved_chars(Iter first, Iter last) {
+
+ // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+
+ const auto is_unreserved = [](char c)
+ {
+ return std::isalnum(c, std::locale())
+ || '-' == c
+ || '.' == c
+ || '_' == c
+ || '~' == c;
+ };
+
+ auto it = first, it2 = first;
+ while (it != last) {
+ if (*it == '%') {
+ const auto sfirst = it;
+ const auto opt_char = percent_encode(sfirst);
+ if (opt_char && is_unreserved(*opt_char)) {
+ *it2 = *opt_char;
+ ++it; ++it;
+ } else {
+ *it2 = *it;
+ }
+ }
+ else {
+ *it2 = *it;
+ }
+ ++it; ++it2;
+ }
+ return it2;
+}
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_URI_PERCENT_ENCODE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.cpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.cpp
new file mode 100644
index 0000000000..ca66405123
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.cpp
@@ -0,0 +1,91 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Copyright 2013 Hannes Kamecke.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "uri_resolve.hpp"
+#include <algorithm>
+
+#ifdef NETWORK_URI_EXTERNAL_BOOST
+#include <boost/algorithm/string/find.hpp>
+#include <boost/algorithm/string/erase.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+namespace boost = boost;
+#else // NETWORK_URI_EXTERNAL_BOOST
+#include "boost/algorithm/string/find.hpp"
+#include "boost/algorithm/string/erase.hpp"
+#include "boost/algorithm/string/replace.hpp"
+#include "boost/algorithm/string/predicate.hpp"
+#endif // NETWORK_URI_EXTERNAL_BOOST
+
+namespace network {
+namespace detail {
+// remove_dot_segments
+inline
+void remove_last_segment(std::string& path) {
+ while (!path.empty()) {
+ if (path.back() == '/') {
+ path.pop_back();
+ break;
+ }
+ path.pop_back();
+ }
+}
+
+// implementation of http://tools.ietf.org/html/rfc3986#section-5.2.4
+static
+std::string remove_dot_segments(std::string input) {
+ std::string result;
+
+ while (!input.empty()) {
+ if (boost::starts_with(input, "../")) {
+ boost::erase_head(input, 3);
+ } else if (boost::starts_with(input, "./")) {
+ boost::erase_head(input, 2);
+ } else if (boost::starts_with(input, "/./")) {
+ boost::replace_head(input, 3, "/");
+ } else if (input == "/.") {
+ boost::replace_head(input, 2, "/");
+ } else if (boost::starts_with(input, "/../")) {
+ boost::erase_head(input, 3);
+ remove_last_segment(result);
+ } else if (boost::starts_with(input, "/..")) {
+ boost::replace_head(input, 3, "/");
+ remove_last_segment(result);
+ } else if (boost::algorithm::all(input, [](char ch) { return ch == '.'; })) {
+ input.clear();
+ }
+ else {
+ int n = (input.front() == '/')? 1 : 0;
+ auto slash = boost::find_nth(input, "/", n);
+ result.append(std::begin(input), std::begin(slash));
+ input.erase(std::begin(input), std::begin(slash));
+ }
+ }
+ return result;
+}
+
+std::string remove_dot_segments(string_view path) {
+ return remove_dot_segments(path.to_string());
+}
+
+// implementation of http://tools.ietf.org/html/rfc3986#section-5.2.3
+std::string merge_paths(const uri& base, const uri& reference) {
+ std::string result;
+
+ if (!base.has_path() || base.path().empty()) {
+ result = "/";
+ } else {
+ const auto& base_path = base.path();
+ auto last_slash = boost::find_last(base_path, "/");
+ result.append(std::begin(base_path), std::end(last_slash));
+ }
+ if (reference.has_path()) {
+ result.append(reference.path().to_string());
+ }
+ return remove_dot_segments(string_view(result));
+}
+} // namespace detail
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.hpp b/graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.hpp
new file mode 100644
index 0000000000..898c6d5423
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/detail/uri_resolve.hpp
@@ -0,0 +1,22 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Copyright 2013 Hannes Kamecke.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_DETAIL_RESOLVE_INC
+#define NETWORK_DETAIL_RESOLVE_INC
+
+#include <network/uri/uri.hpp>
+
+namespace network {
+namespace detail {
+// implementation of http://tools.ietf.org/html/rfc3986#section-5.2.4
+std::string remove_dot_segments(string_view input);
+
+// implementation of http://tools.ietf.org/html/rfc3986#section-5.2.3
+std::string merge_paths(const uri &base, const uri &reference);
+} // namespace detail
+} // namespace network
+
+#endif // NETWORK_DETAIL_RESOLVE_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/uri.cpp b/graphics/asymptote/LspCpp/network/uri/uri.cpp
new file mode 100644
index 0000000000..ee9aee45f1
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri.cpp
@@ -0,0 +1,701 @@
+// Copyright 2012-2017 Glyn Matthews.
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <cassert>
+#include <locale>
+#include <algorithm>
+#include <functional>
+#include "network/uri/uri.hpp"
+#include "detail/uri_parse.hpp"
+#include "detail/uri_advance_parts.hpp"
+#include "detail/uri_percent_encode.hpp"
+#include "detail/uri_normalize.hpp"
+#include "detail/uri_resolve.hpp"
+#include "detail/algorithm.hpp"
+
+namespace network {
+namespace {
+// With the parser, we use string_views, which are mutable. However,
+// there are times (e.g. during normalization), when we want a part
+// to be mutable. This function returns a pair of
+// std::string::iterators in the same range as the URI part.
+//
+inline std::pair<std::string::iterator, std::string::iterator> mutable_part(
+ std::string &str, detail::uri_part part) {
+ auto view = string_view(str);
+
+ auto first_index = std::distance(std::begin(view), std::begin(part));
+ auto first = std::begin(str);
+ std::advance(first, first_index);
+
+ auto last_index = std::distance(std::begin(view), std::end(part));
+ auto last = std::begin(str);
+ std::advance(last, last_index);
+
+ return std::make_pair(first, last);
+}
+
+// This is a convenience function that converts a part of a
+// std::string to a string_view.
+inline string_view to_string_view(const std::string &uri,
+ detail::uri_part part) {
+ if (!part.empty()) {
+ const char *c_str = uri.c_str();
+ const char *part_begin = &(*(std::begin(part)));
+ std::advance(c_str, std::distance(c_str, part_begin));
+ return string_view(c_str, std::distance(std::begin(part), std::end(part)));
+ }
+ return string_view();
+}
+
+inline optional<std::string> make_arg(optional<string_view> view) {
+ if (view) {
+ return view->to_string();
+ }
+ return nullopt;
+}
+
+template <class T>
+inline void ignore(T) {}
+} // namespace
+
+void uri::initialize(optional<string_type> scheme,
+ optional<string_type> user_info,
+ optional<string_type> host, optional<string_type> port,
+ optional<string_type> path, optional<string_type> query,
+ optional<string_type> fragment) {
+ if (scheme) {
+ uri_.append(*scheme);
+ }
+
+ if (user_info || host || port) {
+ if (scheme) {
+ uri_.append("://");
+ }
+
+ if (user_info) {
+ uri_.append(*user_info);
+ uri_.append("@");
+ }
+
+ if (host) {
+ uri_.append(*host);
+ } else {
+ throw uri_builder_error();
+ }
+
+ if (port) {
+ uri_.append(":");
+ uri_.append(*port);
+ }
+ } else {
+ if (scheme) {
+ if (path || query || fragment) {
+ uri_.append(":");
+ } else {
+ throw uri_builder_error();
+ }
+ }
+ }
+
+ if (path) {
+ // if the URI is not opaque and the path is not already prefixed
+ // with a '/', add one.
+ if (host && (!path->empty() && path->front() != '/')) {
+ path = "/" + *path;
+ }
+ uri_.append(*path);
+ }
+
+ if (query) {
+ uri_.append("?");
+ uri_.append(*query);
+ }
+
+ if (fragment) {
+ uri_.append("#");
+ uri_.append(*fragment);
+ }
+
+ uri_view_ = string_view(uri_);
+
+ auto it = std::begin(uri_view_);
+ if (scheme) {
+ uri_parts_.scheme = detail::copy_part(*scheme, it);
+ // ignore : and ://
+ if (*it == ':') {
+ ++it;
+ }
+ if (*it == '/' && *(it + 1) == '/') {
+ it += 2;
+ }
+ }
+
+ if (user_info) {
+ uri_parts_.hier_part.user_info = detail::copy_part(*user_info, it);
+ ++it; // ignore @
+ }
+
+ if (host) {
+ uri_parts_.hier_part.host = detail::copy_part(*host, it);
+ }
+
+ if (port) {
+ ++it; // ignore :
+ uri_parts_.hier_part.port = detail::copy_part(*port, it);
+ }
+
+ if (path) {
+ uri_parts_.hier_part.path = detail::copy_part(*path, it);
+ }
+
+ if (query) {
+ ++it; // ignore ?
+ uri_parts_.query = detail::copy_part(*query, it);
+ }
+
+ if (fragment) {
+ ++it; // ignore #
+ uri_parts_.fragment = detail::copy_part(*fragment, it);
+ }
+}
+
+uri::uri() : uri_view_(uri_) {}
+
+uri::uri(const uri &other) : uri_(other.uri_), uri_view_(uri_) {
+ detail::advance_parts(uri_view_, uri_parts_, other.uri_parts_);
+}
+
+uri::uri(const uri_builder &builder) {
+ initialize(builder.scheme_, builder.user_info_, builder.host_, builder.port_,
+ builder.path_, builder.query_, builder.fragment_);
+}
+
+uri::uri(uri &&other) noexcept : uri_(std::move(other.uri_)),
+ uri_view_(uri_),
+ uri_parts_(std::move(other.uri_parts_)) {
+ detail::advance_parts(uri_view_, uri_parts_, other.uri_parts_);
+ other.uri_.clear();
+ other.uri_view_ = string_view(other.uri_);
+ other.uri_parts_ = detail::uri_parts();
+}
+
+uri::~uri() {}
+
+uri &uri::operator=(uri other) {
+ other.swap(*this);
+ return *this;
+}
+
+void uri::swap(uri &other) noexcept {
+ uri_.swap(other.uri_);
+ uri_view_ = uri_;
+ other.uri_view_ = other.uri_;
+
+ const auto this_parts = uri_parts_;
+ uri_parts_.clear();
+ detail::advance_parts(uri_view_, uri_parts_, other.uri_parts_);
+ other.uri_parts_.clear();
+ detail::advance_parts(other.uri_view_, other.uri_parts_, this_parts);
+}
+
+uri::const_iterator uri::begin() const noexcept { return uri_view_.begin(); }
+
+uri::const_iterator uri::end() const noexcept { return uri_view_.end(); }
+
+bool uri::has_scheme() const noexcept {
+ return static_cast<bool>(uri_parts_.scheme);
+}
+
+uri::string_view uri::scheme() const noexcept {
+ return has_scheme() ? to_string_view(uri_, *uri_parts_.scheme)
+ : string_view{};
+}
+
+bool uri::has_user_info() const noexcept {
+ return static_cast<bool>(uri_parts_.hier_part.user_info);
+}
+
+uri::string_view uri::user_info() const noexcept {
+ return has_user_info()
+ ? to_string_view(uri_, *uri_parts_.hier_part.user_info)
+ : string_view{};
+}
+
+bool uri::has_host() const noexcept {
+ return static_cast<bool>(uri_parts_.hier_part.host);
+}
+
+uri::string_view uri::host() const noexcept {
+ return has_host() ? to_string_view(uri_, *uri_parts_.hier_part.host)
+ : string_view{};
+}
+
+bool uri::has_port() const noexcept {
+ return static_cast<bool>(uri_parts_.hier_part.port);
+}
+
+uri::string_view uri::port() const noexcept {
+ return has_port() ? to_string_view(uri_, *uri_parts_.hier_part.port)
+ : string_view{};
+}
+
+bool uri::has_path() const noexcept {
+ return static_cast<bool>(uri_parts_.hier_part.path);
+}
+
+uri::string_view uri::path() const noexcept {
+ return has_path() ? to_string_view(uri_, *uri_parts_.hier_part.path)
+ : string_view{};
+}
+
+bool uri::has_query() const noexcept {
+ return static_cast<bool>(uri_parts_.query);
+}
+
+uri::string_view uri::query() const noexcept {
+ return has_query() ? to_string_view(uri_, *uri_parts_.query) : string_view{};
+}
+
+uri::query_iterator::query_iterator() : query_{}, kvp_{} {}
+
+uri::query_iterator::query_iterator(optional<detail::uri_part> query)
+ : query_(query)
+ , kvp_{} {
+ if (query_ && query_->empty()) {
+ query_ = nullopt;
+ }
+ else {
+ assign_kvp();
+ }
+}
+
+uri::query_iterator::query_iterator(const query_iterator &other)
+ : query_(other.query_)
+ , kvp_(other.kvp_) {}
+
+uri::query_iterator &uri::query_iterator::operator = (const query_iterator &other) {
+ auto tmp(other);
+ swap(tmp);
+ return *this;
+}
+
+uri::query_iterator::reference uri::query_iterator::operator ++ () noexcept {
+ increment();
+ return kvp_;
+}
+
+uri::query_iterator::value_type uri::query_iterator::operator ++ (int) noexcept {
+ auto original = kvp_;
+ increment();
+ return original;
+}
+
+uri::query_iterator::reference uri::query_iterator::operator * () const noexcept {
+ return kvp_;
+}
+
+uri::query_iterator::pointer uri::query_iterator::operator -> () const noexcept {
+ return std::addressof(kvp_);
+}
+
+bool uri::query_iterator::operator==(const query_iterator &other) const noexcept {
+ if (!query_ && !other.query_) {
+ return true;
+ }
+ else if (query_ && other.query_) {
+ // since we're comparing substrings, the address of the first
+ // element in each iterator must be the same
+ return std::addressof(kvp_.first) == std::addressof(other.kvp_.first);
+ }
+ return false;
+}
+
+void uri::query_iterator::swap(query_iterator &other) noexcept {
+ std::swap(query_, other.query_);
+ std::swap(kvp_, other.kvp_);
+}
+
+void uri::query_iterator::advance_to_next_kvp() noexcept {
+ auto first = std::begin(*query_), last = std::end(*query_);
+
+ auto sep_it = std::find_if(
+ first, last, [](char c) -> bool { return c == '&' || c == ';'; });
+
+ if (sep_it != last) {
+ ++sep_it; // skip next separator
+ }
+
+ // reassign query to the next element
+ query_ = detail::uri_part(sep_it, last);
+}
+
+void uri::query_iterator::assign_kvp() noexcept {
+ auto first = std::begin(*query_), last = std::end(*query_);
+
+ auto sep_it = std::find_if(
+ first, last, [](char c) -> bool { return c == '&' || c == ';'; });
+ auto eq_it =
+ std::find_if(first, sep_it, [](char c) -> bool { return c == '='; });
+
+ kvp_.first = string_view(std::addressof(*first), std::distance(first, eq_it));
+ if (eq_it != sep_it) {
+ ++eq_it; // skip '=' symbol
+ }
+ kvp_.second = string_view(std::addressof(*eq_it), std::distance(eq_it, sep_it));
+}
+
+void uri::query_iterator::increment() noexcept {
+ assert(query_);
+
+ if (!query_->empty()) {
+ advance_to_next_kvp();
+ assign_kvp();
+ }
+
+ if (query_->empty()) {
+ query_ = nullopt;
+ }
+}
+
+uri::query_iterator uri::query_begin() const noexcept {
+ return has_query()? uri::query_iterator{uri_parts_.query} : uri::query_iterator{};
+}
+
+uri::query_iterator uri::query_end() const noexcept {
+ return uri::query_iterator{};
+}
+
+bool uri::has_fragment() const noexcept {
+ return static_cast<bool>(uri_parts_.fragment);
+}
+
+uri::string_view uri::fragment() const noexcept {
+ return has_fragment() ? to_string_view(uri_, *uri_parts_.fragment)
+ : string_view{};
+}
+
+bool uri::has_authority() const noexcept {
+ return has_host();
+}
+
+uri::string_view uri::authority() const noexcept {
+ if (!has_host()) {
+ return string_view{};
+ }
+
+ auto host = this->host();
+
+ auto user_info = string_view{};
+ if (has_user_info()) {
+ user_info = this->user_info();
+ }
+
+ auto port = string_view{};
+ if (has_port()) {
+ port = this->port();
+ }
+
+ auto first = std::begin(host), last = std::end(host);
+ if (has_user_info() && !user_info.empty()) {
+ first = std::begin(user_info);
+ }
+ else if (host.empty() && has_port() && !port.empty()) {
+ first = std::begin(port);
+ --first; // include ':' before port
+ }
+
+ if (host.empty()) {
+ if (has_port() && !port.empty()) {
+ last = std::end(port);
+ }
+ else if (has_user_info() && !user_info.empty()) {
+ last = std::end(user_info);
+ ++last; // include '@'
+ }
+ }
+ else if (has_port()) {
+ if (port.empty()) {
+ ++last; // include ':' after host
+ }
+ else {
+ last = std::end(port);
+ }
+ }
+
+ return string_view(first, std::distance(first, last));
+}
+
+std::string uri::string() const { return uri_; }
+
+std::wstring uri::wstring() const {
+ return std::wstring(std::begin(*this), std::end(*this));
+}
+
+std::u16string uri::u16string() const {
+ return std::u16string(std::begin(*this), std::end(*this));
+}
+
+std::u32string uri::u32string() const {
+ return std::u32string(std::begin(*this), std::end(*this));
+}
+
+uri::string_view uri::view() const noexcept {
+ return uri_view_;
+}
+
+bool uri::empty() const noexcept { return uri_.empty(); }
+
+bool uri::is_absolute() const noexcept { return has_scheme(); }
+
+bool uri::is_opaque() const noexcept {
+ return (is_absolute() && !has_authority());
+}
+
+uri uri::normalize(uri_comparison_level level) const {
+ string_type normalized(uri_);
+ string_view normalized_view(normalized);
+ detail::uri_parts parts;
+ detail::advance_parts(normalized_view, parts, uri_parts_);
+
+ if (uri_comparison_level::syntax_based == level) {
+ // All alphabetic characters in the scheme and host are
+ // lower-case...
+ if (parts.scheme) {
+ std::string::iterator first, last;
+ std::tie(first, last) = mutable_part(normalized, *parts.scheme);
+ std::transform(first, last, first,
+ [](char ch) { return std::tolower(ch, std::locale()); });
+ }
+
+ // if (parts.hier_part.host) {
+ // std::string::iterator first, last;
+ // std::tie(first, last) = mutable_part(normalized, *parts.hier_part.host);
+ // std::transform(first, last, first,
+ // [](char ch) { return std::tolower(ch, std::locale()); });
+ // }
+
+ // ...except when used in percent encoding
+ detail::for_each(normalized, detail::percent_encoded_to_upper<std::string>());
+
+ // parts are invalidated here
+ // there's got to be a better way of doing this that doesn't
+ // mean parsing again (twice!)
+ normalized.erase(detail::decode_encoded_unreserved_chars(
+ std::begin(normalized), std::end(normalized)),
+ std::end(normalized));
+ normalized_view = string_view(normalized);
+
+ // need to parse the parts again as the underlying string has changed
+ const_iterator it = std::begin(normalized_view), last = std::end(normalized_view);
+ bool is_valid = detail::parse(it, last, parts);
+ ignore(is_valid);
+ assert(is_valid);
+
+ if (parts.hier_part.path) {
+ uri::string_type path = detail::normalize_path_segments(
+ to_string_view(normalized, *parts.hier_part.path));
+
+ // put the normalized path back into the uri
+ optional<string_type> query, fragment;
+ if (parts.query) {
+ query = parts.query->to_string();
+ }
+
+ if (parts.fragment) {
+ fragment = parts.fragment->to_string();
+ }
+
+ auto path_begin = std::begin(normalized);
+ auto path_range = mutable_part(normalized, *parts.hier_part.path);
+ std::advance(path_begin, std::distance(path_begin, path_range.first));
+ normalized.erase(path_begin, std::end(normalized));
+ normalized.append(path);
+
+ if (query) {
+ normalized.append("?");
+ normalized.append(*query);
+ }
+
+ if (fragment) {
+ normalized.append("#");
+ normalized.append(*fragment);
+ }
+ }
+ }
+
+ return uri(normalized);
+}
+
+uri uri::make_relative(const uri &other) const {
+ if (is_opaque() || other.is_opaque()) {
+ return other;
+ }
+
+ if ((!has_scheme() || !other.has_scheme()) ||
+ !detail::equal(scheme(), other.scheme())) {
+ return other;
+ }
+
+ if ((!has_authority() || !other.has_authority()) ||
+ !detail::equal(authority(), other.authority())) {
+ return other;
+ }
+
+ if (!has_path() || !other.has_path()) {
+ return other;
+ }
+
+ auto path =
+ detail::normalize_path(this->path(), uri_comparison_level::syntax_based);
+ auto other_path = detail::normalize_path(other.path(),
+ uri_comparison_level::syntax_based);
+
+ optional<string_type> query, fragment;
+ if (other.has_query()) {
+ query = other.query().to_string();
+ }
+
+ if (other.has_fragment()) {
+ fragment = other.fragment().to_string();
+ }
+
+ network::uri result;
+ result.initialize(optional<string_type>(), optional<string_type>(),
+ optional<string_type>(), optional<string_type>(),
+ other_path, query, fragment);
+ return result;
+}
+
+uri uri::resolve(const uri &base) const {
+ // This implementation uses the psuedo-code given in
+ // http://tools.ietf.org/html/rfc3986#section-5.2.2
+
+ if (is_absolute() && !is_opaque()) {
+ // throw an exception ?
+ return *this;
+ }
+
+ if (is_opaque()) {
+ // throw an exception ?
+ return *this;
+ }
+
+ optional<uri::string_type> user_info, host, port, path, query, fragment;
+
+ if (has_authority()) {
+ // g -> http://g
+ if (has_user_info()) {
+ user_info = make_arg(this->user_info());
+ }
+
+ if (has_host()) {
+ host = make_arg(this->host());
+ }
+
+ if (has_port()) {
+ port = make_arg(this->port());
+ }
+
+ if (has_path()) {
+ path = detail::remove_dot_segments(this->path());
+ }
+
+ if (has_query()) {
+ query = make_arg(this->query());
+ }
+ } else {
+ if (!has_path() || this->path().empty()) {
+ if (base.has_path()) {
+ path = make_arg(base.path());
+ }
+
+ if (has_query()) {
+ query = make_arg(this->query());
+ } else if (base.has_query()) {
+ query = make_arg(base.query());
+ }
+ } else {
+ if (this->path().front() == '/') {
+ path = detail::remove_dot_segments(this->path());
+ } else {
+ path = detail::merge_paths(base, *this);
+ }
+
+ if (has_query()) {
+ query = make_arg(this->query());
+ }
+ }
+
+ if (base.has_user_info()) {
+ user_info = make_arg(base.user_info());
+ }
+
+ if (base.has_host()) {
+ host = make_arg(base.host());
+ }
+
+ if (base.has_port()) {
+ port = make_arg(base.port());
+ }
+ }
+
+ if (has_fragment()) {
+ fragment = make_arg(this->fragment());
+ }
+
+ network::uri result;
+ result.initialize(make_arg(base.scheme()), std::move(user_info),
+ std::move(host), std::move(port), std::move(path),
+ std::move(query), std::move(fragment));
+ return result;
+}
+
+int uri::compare(const uri &other, uri_comparison_level level) const noexcept {
+ // if both URIs are empty, then we should define them as equal
+ // even though they're still invalid.
+ if (empty() && other.empty()) {
+ return 0;
+ }
+
+ if (empty()) {
+ return -1;
+ }
+
+ if (other.empty()) {
+ return 1;
+ }
+
+ return normalize(level).uri_.compare(other.normalize(level).uri_);
+}
+
+bool uri::initialize(const string_type &uri) {
+ uri_ = detail::trim_copy(uri);
+ if (!uri_.empty()) {
+ uri_view_ = string_view(uri_);
+ const_iterator it = std::begin(uri_view_), last = std::end(uri_view_);
+ bool is_valid = detail::parse(it, last, uri_parts_);
+ return is_valid;
+ }
+ return true;
+}
+
+void swap(uri &lhs, uri &rhs) noexcept { lhs.swap(rhs); }
+
+bool operator==(const uri &lhs, const uri &rhs) noexcept {
+ return lhs.view() == rhs.view();
+}
+
+bool operator==(const uri &lhs, const char *rhs) noexcept {
+ return lhs.view() == string_view{rhs};
+}
+
+bool operator<(const uri &lhs, const uri &rhs) noexcept {
+ return lhs.view() < rhs.view();
+}
+
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/uri.hpp b/graphics/asymptote/LspCpp/network/uri/uri.hpp
new file mode 100644
index 0000000000..429e2caeff
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri.hpp
@@ -0,0 +1,758 @@
+// Copyright 2009-2010 Jeroen Habraken.
+// Copyright 2009-2017 Dean Michael Berris, Glyn Matthews.
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_INC
+#define NETWORK_URI_INC
+
+/**
+ * \file
+ * \brief Contains the uri class.
+ */
+
+#include <iterator>
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <string>
+#include <cstdlib>
+#include <network/string_view.hpp>
+#include <network/optional.hpp>
+#include <network/uri/config.hpp>
+#include <network/uri/uri_errors.hpp>
+#include <network/uri/detail/uri_parts.hpp>
+#include <network/uri/detail/encode.hpp>
+#include <network/uri/detail/decode.hpp>
+#include <network/uri/detail/translate.hpp>
+
+#ifdef NETWORK_URI_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4251 4231 4660)
+#endif
+
+namespace network {
+/**
+ * \enum uri_comparison_level
+ * \brief Defines the steps on the URI comparison ladder.
+ */
+enum class uri_comparison_level {
+ string_comparison,
+ syntax_based,
+ scheme_based,
+};
+
+/**
+ * \ingroup uri
+ * \class uri_builder network/uri/uri_builder.hpp network/uri.hpp
+ * \brief A class that allows complex uri objects to be constructed.
+ * \sa uri
+ */
+class uri_builder;
+
+/**
+ * \ingroup uri
+ * \class uri network/uri/uri.hpp network/uri.hpp
+ * \brief A class that parses a URI (Uniform Resource Identifier)
+ * into its component parts.
+ *
+ * This class conforms to a URI as defined by RFC 3986, RFC 3987 and
+ * RFC 2732, including scoped IDs. It provides member functions for
+ * normalizing, comparing and resolving URIs.
+ *
+ * A URI has the syntax:
+ *
+ * \code
+ * [scheme:][user_info@][host][:port][path][?query][#fragment]
+ * \endcode
+ *
+ * Example:
+ *
+ * \code
+ * network::uri instance("http://cpp-netlib.org/");
+ * assert(instance.is_absolute());
+ * assert(!instance.is_opaque());
+ * assert(instance.scheme());
+ * assert("http" == *instance.scheme());
+ * assert(instance.host());
+ * assert("cpp-netlib.org" == *instance.host());
+ * assert(instance.path());
+ * assert("/" == *instance.path());
+ * \endcode
+ */
+class uri {
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ friend class uri_builder;
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ public:
+ /**
+ * \brief The URI string_type.
+ */
+ typedef std::string string_type;
+
+ /**
+ * \brief A reference to the underlying string_type parts.
+ */
+ typedef network::string_view string_view;
+
+ /**
+ * \brief The char traits.
+ */
+ typedef string_view::traits_type traits_type;
+
+ /**
+ * \brief The URI const_iterator type.
+ */
+ typedef string_view::const_iterator const_iterator;
+
+ /**
+ * \brief The URI iterator type.
+ */
+ typedef const_iterator iterator;
+
+ /**
+ * \brief The URI value_type.
+ */
+ typedef std::iterator_traits<iterator>::value_type value_type;
+
+ /**
+ *
+ */
+ class query_iterator {
+ public:
+ using value_type = std::pair<string_view, string_view>;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const value_type *;
+ using reference = const value_type &;
+ using iterator_category = std::forward_iterator_tag;
+
+ query_iterator();
+ explicit query_iterator(optional<detail::uri_part>);
+ query_iterator(const query_iterator &);
+ query_iterator &operator=(const query_iterator &);
+ reference operator++() noexcept;
+ value_type operator++(int) noexcept;
+ reference operator*() const noexcept;
+ pointer operator->() const noexcept;
+ bool operator==(const query_iterator &) const noexcept;
+ inline bool operator!=(const query_iterator &other) const noexcept {
+ return !(*this == other);
+ }
+
+ private:
+ void swap(query_iterator &) noexcept;
+ void advance_to_next_kvp() noexcept;
+ void assign_kvp() noexcept;
+ void increment() noexcept;
+
+ optional<detail::uri_part> query_;
+ value_type kvp_;
+ };
+
+ /**
+ * \brief Default constructor.
+ */
+ uri();
+
+ /**
+ * \brief Constructor.
+ * \param first The first element in a string sequence.
+ * \param last The end + 1th element in a string sequence.
+ * \throws uri_syntax_error if the sequence is not a valid URI.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ template <class InputIter>
+ uri(InputIter first, InputIter last) {
+ if (!initialize(string_type(first, last))) {
+ throw uri_syntax_error();
+ }
+ }
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ template <class InputIter>
+ explicit uri(InputIter first, InputIter last, std::error_code &ec) {
+ if (!initialize(string_type(first, last))) {
+ ec = make_error_code(uri_error::invalid_syntax);
+ }
+ }
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ /**
+ * \brief Constructor.
+ * \param source A source string that is to be parsed as a URI.
+ * \throws uri_syntax_error if the source is not a valid URI.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ template <class Source>
+ explicit uri(const Source &source) {
+ if (!initialize(detail::translate(source))) {
+ throw uri_syntax_error();
+ }
+ }
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ template <class Source>
+ explicit uri(const Source &source, std::error_code &ec) {
+ if (!initialize(detail::translate(source))) {
+ ec = make_error_code(uri_error::invalid_syntax);
+ }
+ }
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ explicit uri(const uri_builder &builder);
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ /**
+ * \brief Copy constructor.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ uri(const uri &other);
+
+ /**
+ * \brief Move constructor.
+ */
+ uri(uri &&other) noexcept;
+
+ /**
+ * \brief Destructor.
+ */
+ ~uri();
+
+ /**
+ * \brief Assignment operator.
+ * \throws std::bad_alloc If the underlying string cannot be allocated.
+ */
+ uri &operator=(uri other);
+
+ /**
+ * \brief Swaps one uri object with another.
+ * \param other The other uri object.
+ */
+ void swap(uri &other) noexcept;
+
+ /**
+ * \brief Returns an iterator at the first element in the
+ * underlying sequence.
+ * \return An iterator starting at the first element.
+ */
+ const_iterator begin() const noexcept;
+
+ /**
+ * \brief Returns an iterator at the end + 1th element in the
+ * underlying sequence.
+ * \return An iterator starting at the end + 1th element.
+ */
+ const_iterator end() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a scheme component.
+ * \return \c true if the URI has a scheme, \c false otherwise.
+ */
+ bool has_scheme() const noexcept;
+
+ /**
+ * \brief Returns the URI scheme.
+ * \return The scheme.
+ * \pre has_scheme()
+ */
+ string_view scheme() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a user info component.
+ * \return \c true if the URI has a user info, \c false otherwise.
+ */
+ bool has_user_info() const noexcept;
+
+ /**
+ * \brief Returns the URI user info.
+ * \return The user info.
+ * \pre has_user_info()
+ */
+ string_view user_info() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a host component.
+ * \return \c true if the URI has a host, \c false otherwise.
+ */
+ bool has_host() const noexcept;
+
+ /**
+ * \brief Returns the URI host.
+ * \return The host.
+ * \pre has_host()
+ */
+ string_view host() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a port component.
+ * \return \c true if the URI has a port, \c false otherwise.
+ */
+ bool has_port() const noexcept;
+
+ /**
+ * \brief Returns the URI port.
+ * \return The port.
+ * \pre has_port()
+ */
+ string_view port() const noexcept;
+
+ /**
+ * \brief Returns the URI port as an integer.
+ * \return The port number.
+ * \pre has_port()
+ */
+ template <typename intT>
+ intT port(typename std::is_integral<intT>::type * = 0) const {
+ assert(has_port());
+ auto p = port();
+ const char *port_first = std::addressof(*p.begin());
+ char *port_last = 0;
+ return static_cast<intT>(std::strtoul(port_first, &port_last, 10));
+ }
+
+ /**
+ * \brief Tests whether this URI has a path component.
+ * \return \c true if the URI has a path, \c false otherwise.
+ */
+ bool has_path() const noexcept;
+
+ /**
+ * \brief Returns the URI path.
+ * \return The path.
+ * \pre has_path()
+ */
+ string_view path() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a query component.
+ * \return \c true if the URI has a query, \c false otherwise.
+ */
+ bool has_query() const noexcept;
+
+ /**
+ * \brief Returns the URI query.
+ * \return The query.
+ * \pre has_query()
+ */
+ string_view query() const noexcept;
+
+ /**
+ * \brief Returns an iterator to the first key-value pair in the query
+ * component.
+ *
+ * \return query_iterator.
+ */
+ query_iterator query_begin() const noexcept;
+
+ /**
+ * \brief Returns an iterator to the last key-value pair in the query
+ * component.
+ *
+ * \return query_iterator.
+ */
+ query_iterator query_end() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a fragment component.
+ * \return \c true if the URI has a fragment, \c false otherwise.
+ */
+ bool has_fragment() const noexcept;
+
+ /**
+ * \brief Returns the URI fragment.
+ * \return The fragment.
+ * \pre has_fragment()
+ */
+ string_view fragment() const noexcept;
+
+ /**
+ * \brief Tests whether this URI has a valid authority.
+ * \return \c true if the URI has an authority, \c false otherwise.
+ */
+ bool has_authority() const noexcept;
+
+ /**
+ * \brief Returns the URI authority.
+ * \return The authority.
+ */
+ string_view authority() const noexcept;
+
+ /**
+ * \brief Returns the URI as a std::basic_string object.
+ * \return A URI string.
+ */
+ template <class charT, class traits = std::char_traits<charT>,
+ class Allocator = std::allocator<charT> >
+ std::basic_string<charT, traits, Allocator> to_string(
+ const Allocator &alloc = Allocator()) const {
+ return std::basic_string<charT, traits, Allocator>(begin(), end());
+ }
+
+ /**
+ * \brief Returns the URI as a std::string object.
+ * \returns A URI string.
+ */
+ std::string string() const;
+
+ /**
+ * \brief Returns the URI as a std::wstring object.
+ * \returns A URI string.
+ */
+ std::wstring wstring() const;
+
+ /**
+ * \brief Returns the URI as a std::u16string object.
+ * \returns A URI string.
+ */
+ std::u16string u16string() const;
+
+ /**
+ * \brief Returns the URI as a std::u32string object.
+ * \returns A URI string.
+ */
+ std::u32string u32string() const;
+
+ /**
+ * \brief Returns the URI as a string_view object.
+ * \returns A URI string view.
+ */
+ string_view view() const noexcept;
+
+ /**
+ * \brief Checks if the uri object is empty, i.e. it has no parts.
+ * \returns \c true if there are no parts, \c false otherwise.
+ */
+ bool empty() const noexcept;
+
+ /**
+ * \brief Checks if the uri is absolute, i.e. it has a scheme.
+ * \returns \c true if it is absolute, \c false if it is relative.
+ */
+ bool is_absolute() const noexcept;
+
+ /**
+ * \brief Checks if the uri is opaque, i.e. if it doesn't have an
+ * authority.
+ * \returns \c true if it is opaque, \c false if it is hierarchical.
+ */
+ bool is_opaque() const noexcept;
+
+ /**
+ * \brief Normalizes a uri object at a given level in the
+ * comparison ladder.
+ * \param level The comparison level.
+ * \returns A normalized uri.
+ * \post compare(normalize(uri, level), level) == 0
+ * \throws std::bad_alloc
+ */
+ uri normalize(uri_comparison_level level) const;
+
+ /**
+ * \brief Returns a relative reference against the base URI.
+ * \param base The base URI.
+ * \returns A relative reference of this URI against the base.
+ * \throws std::bad_alloc
+ */
+ uri make_relative(const uri &base) const;
+
+ /**
+ * \brief Resolves a relative reference against the given URI.
+ * \param base The base URI to resolve against.
+ * \returns An absolute URI.
+ * \throws std::bad_alloc
+ */
+ uri resolve(const uri &base) const;
+
+ /**
+ * \brief Compares this URI against another, corresponding to the
+ * level in the comparison ladder.
+ * \param other The other URI.
+ * \param level The level in the comparison ladder.
+ * \returns \c 0 if the URIs are considered equal, \c -1 if this is
+ * less than other and and 1 if this is greater than
+ * other.
+ */
+ int compare(const uri &other, uri_comparison_level level) const noexcept;
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * user info part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_user_info(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_user_info(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * host part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_host(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_host(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * port part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_port(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_port(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * path part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_path(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_path(first, last, out);
+ }
+
+ /**
+ * \deprecated Avoid using this function
+ * \brief Equivalent to \c encode_query_component
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ * \sa encode_query_commponent
+ * \sa encode_query_key_value_pair
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_query(InputIter first, InputIter last,
+ OutputIter out) {
+ return encode_query_component(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * query component, including the '=' character.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_query_component(
+ InputIter first, InputIter last, OutputIter out) {
+ return detail::encode_query_component(first, last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * query key value pair.
+ * \param key_first The iterator at first element in the input
+ * sequence.
+ * \param key_last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_query_key_value_pair(
+ InputIter key_first, InputIter key_last,
+ InputIter value_first, InputIter value_last,
+ OutputIter out) {
+ out = detail::encode_query_component(key_first, key_last, out);
+ out++ = '=';
+ return detail::encode_query_component(value_first, value_last, out);
+ }
+
+ /**
+ * \brief Encodes a sequence according to the rules for encoding a
+ * fragment part.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter encode_fragment(InputIter first, InputIter last,
+ OutputIter out) {
+ return detail::encode_fragment(first, last, out);
+ }
+
+ /**
+ * \brief Decodes a sequence according to the percent decoding
+ * rules.
+ * \param first The iterator at first element in the input
+ * sequence.
+ * \param last The iterator at end + 1th element in the input
+ * sequence.
+ * \param out The iterator at the first element in the output
+ * sequence.
+ * \returns The iterator at the end + 1th in the output sequence.
+ */
+ template <typename InputIter, typename OutputIter>
+ static OutputIter decode(InputIter first, InputIter last, OutputIter out) {
+ return detail::decode(first, last, out);
+ }
+
+ private:
+ bool initialize(const string_type &uri);
+
+ void initialize(optional<string_type> scheme, optional<string_type> user_info,
+ optional<string_type> host, optional<string_type> port,
+ optional<string_type> path, optional<string_type> query,
+ optional<string_type> fragment);
+
+ string_type uri_;
+ string_view uri_view_;
+ detail::uri_parts uri_parts_;
+};
+
+
+/**
+ * \brief \c uri factory function.
+ * \param first The first element in a string sequence.
+ * \param last The end + 1th element in a string sequence.
+ * \param ec Error code set if the sequence is not a valid URI.
+ */
+template <class InputIter>
+inline uri make_uri(InputIter first, InputIter last, std::error_code &ec) {
+ return uri(first, last, ec);
+}
+
+/**
+ * \brief \c uri factory function.
+ * \param source A source string that is to be parsed as a URI.
+ * \param ec Error code set if the source is not a valid URI.
+ */
+template <class Source>
+inline uri make_uri(const Source &source, std::error_code &ec) {
+ return uri(source, ec);
+}
+
+/**
+ * \brief Swaps one uri object with another.
+ */
+void swap(uri &lhs, uri &rhs) noexcept;
+
+/**
+* \brief Equality operator for the \c uri.
+*/
+bool operator==(const uri &lhs, const uri &rhs) noexcept;
+
+/**
+ * \brief Equality operator for the \c uri.
+ */
+bool operator==(const uri &lhs, const char *rhs) noexcept;
+
+/**
+ * \brief Equality operator for the \c uri.
+ */
+inline bool operator==(const char *lhs, const uri &rhs) noexcept {
+ return rhs == lhs;
+}
+
+/**
+ * \brief Inequality operator for the \c uri.
+ */
+inline bool operator!=(const uri &lhs, const uri &rhs) noexcept {
+ return !(lhs == rhs);
+}
+
+/**
+ * \brief Less-than operator for the \c uri.
+ */
+bool operator<(const uri &lhs, const uri &rhs) noexcept;
+
+/**
+ * \brief Greater-than operator for the \c uri.
+ */
+inline bool operator>(const uri &lhs, const uri &rhs) noexcept {
+ return rhs < lhs;
+}
+
+/**
+ * \brief Less-than-or-equal-to operator for the \c uri.
+ */
+inline bool operator<=(const uri &lhs, const uri &rhs) noexcept {
+ return !(rhs < lhs);
+}
+
+/**
+ * \brief Greater-than-or-equal-to operator for the \c uri.
+ */
+inline bool operator>=(const uri &lhs, const uri &rhs) noexcept {
+ return !(lhs < rhs);
+}
+} // namespace network
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+namespace std {
+template <>
+struct is_error_code_enum<network::uri_error> : public true_type {};
+} // namespace std
+
+namespace std {
+template <>
+struct hash<network::uri> {
+ std::size_t operator()(const network::uri &uri_) const {
+ std::size_t seed = 0;
+ std::for_each(std::begin(uri_), std::end(uri_),
+ [&seed](network::uri::value_type v) {
+ std::hash<network::uri::value_type> hasher;
+ seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ });
+ return seed;
+ }
+};
+} // namespace std
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+#ifdef NETWORK_URI_MSVC
+#pragma warning(pop)
+#endif
+
+#include <network/uri/uri_builder.hpp>
+
+#endif // NETWORK_URI_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/uri_builder.cpp b/graphics/asymptote/LspCpp/network/uri/uri_builder.cpp
new file mode 100644
index 0000000000..c8d767ab47
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri_builder.cpp
@@ -0,0 +1,152 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <locale>
+#include "network/uri/uri_builder.hpp"
+#include "detail/uri_normalize.hpp"
+#include "detail/uri_parse_authority.hpp"
+#include "detail/algorithm.hpp"
+
+namespace network {
+uri_builder::uri_builder(const network::uri &base_uri) {
+ if (base_uri.has_scheme()) {
+ scheme_ = base_uri.scheme().to_string();
+ }
+
+ if (base_uri.has_user_info()) {
+ user_info_ = base_uri.user_info().to_string();
+ }
+
+ if (base_uri.has_host()) {
+ host_ = base_uri.host().to_string();
+ }
+
+ if (base_uri.has_port()) {
+ port_ = base_uri.port().to_string();
+ }
+
+ if (base_uri.has_path()) {
+ path_ = base_uri.path().to_string();
+ }
+
+ if (base_uri.has_query()) {
+ query_ = base_uri.query().to_string();
+ }
+
+ if (base_uri.has_fragment()) {
+ fragment_ = base_uri.fragment().to_string();
+ }
+}
+
+uri_builder::~uri_builder() noexcept {}
+
+network::uri uri_builder::uri() const { return network::uri(*this); }
+
+void uri_builder::set_scheme(string_type &&scheme) {
+ // validate scheme is valid and normalize
+ scheme_ = scheme;
+ detail::transform(*scheme_, std::begin(*scheme_),
+ [] (char ch) { return std::tolower(ch, std::locale()); });
+}
+
+void uri_builder::set_user_info(string_type &&user_info) {
+ user_info_ = string_type();
+ network::uri::encode_user_info(std::begin(user_info), std::end(user_info),
+ std::back_inserter(*user_info_));
+}
+
+uri_builder &uri_builder::clear_user_info() {
+ user_info_ = network::nullopt;
+ return *this;
+}
+
+void uri_builder::set_host(string_type &&host) {
+ host_ = string_type();
+ network::uri::encode_host(std::begin(host), std::end(host),
+ std::back_inserter(*host_));
+ detail::transform(*host_, std::begin(*host_),
+ [](char ch) { return std::tolower(ch, std::locale()); });
+}
+
+void uri_builder::set_port(string_type &&port) {
+ port_ = string_type();
+ network::uri::encode_port(std::begin(port), std::end(port),
+ std::back_inserter(*port_));
+}
+
+uri_builder &uri_builder::clear_port() {
+ port_ = network::nullopt;
+ return *this;
+}
+
+void uri_builder::set_authority(string_type &&authority) {
+ optional<detail::uri_part> user_info, host, port;
+ uri::string_view view(authority);
+ uri::const_iterator it = std::begin(view), last = std::end(view);
+ detail::parse_authority(it, last, user_info, host, port);
+
+ if (user_info) {
+ set_user_info(user_info->to_string());
+ }
+
+ if (host) {
+ set_host(host->to_string());
+ }
+
+ if (port) {
+ set_port(port->to_string());
+ }
+}
+
+void uri_builder::set_path(string_type &&path) {
+ path_ = string_type();
+ network::uri::encode_path(std::begin(path), std::end(path),
+ std::back_inserter(*path_));
+}
+
+uri_builder &uri_builder::clear_path() {
+ path_ = network::nullopt;
+ return *this;
+}
+
+void uri_builder::append_query_component(string_type &&name) {
+ if (!query_) {
+ query_ = string_type();
+ }
+ else {
+ query_->append("&");
+ }
+ network::uri::encode_query_component(
+ std::begin(name), std::end(name), std::back_inserter(*query_));
+}
+
+void uri_builder::append_query_key_value_pair(string_type &&key, string_type &&value) {
+ if (!query_) {
+ query_ = string_type();
+ } else {
+ query_->push_back('&');
+ }
+ network::uri::encode_query_key_value_pair(
+ std::begin(key), std::end(key),
+ std::begin(value), std::end(value),
+ std::back_inserter(*query_));
+}
+
+uri_builder &uri_builder::clear_query() {
+ query_ = network::nullopt;
+ return *this;
+}
+
+void uri_builder::set_fragment(string_type &&fragment) {
+ fragment_ = string_type();
+ network::uri::encode_fragment(std::begin(fragment), std::end(fragment),
+ std::back_inserter(*fragment_));
+}
+
+uri_builder &uri_builder::clear_fragment() {
+ fragment_ = network::nullopt;
+ return *this;
+}
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/uri_builder.hpp b/graphics/asymptote/LspCpp/network/uri/uri_builder.hpp
new file mode 100644
index 0000000000..6c6d487b7d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri_builder.hpp
@@ -0,0 +1,277 @@
+// Copyright (c) Glyn Matthews 2012-2016.
+// Copyright 2012 Dean Michael Berris <dberris@google.com>
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file
+ * \brief Contains the definition of the uri_builder.
+ */
+
+#ifndef NETWORK_URI_BUILDER_INC
+#define NETWORK_URI_BUILDER_INC
+
+#include <cstdint>
+#include <utility>
+#include <type_traits>
+#include <network/uri/uri.hpp>
+
+#ifdef NETWORK_URI_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4251 4231 4660)
+#endif
+
+namespace network {
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+namespace detail {
+
+template <class T>
+struct host_converter {
+ uri::string_type operator()(const T &host) const {
+ return detail::translate(host);
+ }
+};
+
+template <class T, class Enable = void>
+struct port_converter {
+ uri::string_type operator()(const T &port) const {
+ return detail::translate(port);
+ }
+};
+
+template <class T>
+struct port_converter<T, typename std::enable_if<std::is_integral<
+ typename std::decay<T>::type>::value>::type> {
+ uri::string_type operator()(std::uint16_t port) const {
+ return std::to_string(port);
+ }
+};
+
+template <class T>
+struct path_converter {
+ uri::string_type operator()(const T &path) const {
+ return detail::translate(path);
+ }
+};
+} // namespace detail
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+/**
+ * \ingroup uri
+ * \class uri_builder network/uri/uri_builder.hpp network/uri.hpp
+ * \brief A class that allows complex uri objects to be constructed.
+ * \sa uri
+ */
+class uri_builder {
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ friend class uri;
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ uri_builder(const uri_builder &) = delete;
+ uri_builder &operator=(const uri_builder &) = delete;
+
+ public:
+ /**
+ * \brief The uri_builder string_type.
+ */
+ using string_type = network::uri::string_type;
+
+ /**
+ * \brief Constructor.
+ */
+ uri_builder() = default;
+
+ /**
+ * \brief Constructor.
+ * \param base A URI that is the base on which a new URI is built.
+ */
+ explicit uri_builder(const uri &base);
+
+ /**
+ * \brief Destructor.
+ */
+ ~uri_builder() noexcept;
+
+ /**
+ * \brief Adds a new scheme to the uri_builder.
+ * \param scheme The scheme.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &scheme(const Source &scheme) {
+ set_scheme(detail::translate(scheme));
+ return *this;
+ }
+
+ /**
+ * \brief Adds a new user info to the uri_builder.
+ * \param user_info The user info.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &user_info(const Source &user_info) {
+ set_user_info(detail::translate(user_info));
+ return *this;
+ }
+
+ /**
+ * \brief Clears the URI user_info part.
+ * \returns \c *this
+ */
+ uri_builder &clear_user_info();
+
+ /**
+ * \brief Adds a new host to the uri_builder.
+ * \param host The host.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &host(const Source &host) {
+ detail::host_converter<Source> convert;
+ set_host(convert(host));
+ return *this;
+ }
+
+ /**
+ * \brief Adds a new port to the uri_builder.
+ * \param port The port.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &port(const Source &port) {
+ detail::port_converter<Source> convert;
+ set_port(convert(port));
+ return *this;
+ }
+
+ /**
+ * \brief Clears the URI port part.
+ * \returns \c *this
+ */
+ uri_builder &clear_port();
+
+ /**
+ * \brief Adds a new authority to the uri_builder.
+ * \param authority The authority.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &authority(const Source &authority) {
+ set_authority(detail::translate(authority));
+ return *this;
+ }
+
+ /**
+ * \brief Adds a new path to the uri_builder.
+ * \param path The path.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &path(const Source &path) {
+ detail::path_converter<Source> convert;
+ set_path(convert(path));
+ return *this;
+ }
+
+ /**
+ * \brief Clears the URI path part.
+ * \returns \c *this
+ */
+ uri_builder &clear_path();
+
+ /**
+ * \deprecated Use append_query_component
+ * \warning This function's behaviour has changed and percent encoding
+ * of the '=' character is not ignored.
+ * \brief Adds a new query to the uri_builder.
+ * \param query The query.
+ * \returns \c *this
+ * \sa append_query_parameter
+ */
+ template <typename Source>
+ uri_builder &append_query(const Source &query) {
+ return append_query_component(query);
+ }
+
+ /**
+ * \brief Appends a new query component to the uri_builder. The
+ * '=' symbol is percent encoded.
+ * \param component The query component.
+ * \returns \c *this
+ * \sa append_query_key_value_pair
+ */
+ template <typename Source>
+ uri_builder &append_query_component(const Source &component) {
+ append_query_component(detail::translate(component));
+ return *this;
+ }
+
+ /**
+ * \brief Adds a new query key/value pair to the uri_builder.
+ * \param key The query parameter key.
+ * \param value The query parameter value.
+ * \returns \c *this
+ */
+ template <typename Key, typename Value>
+ uri_builder &append_query_key_value_pair(const Key &key, const Value &value) {
+ append_query_key_value_pair(detail::translate(key),
+ detail::translate(value));
+ return *this;
+ }
+
+ /**
+ * \brief Clears the URI query part.
+ * \returns \c *this
+ */
+ uri_builder &clear_query();
+
+ /**
+ * \brief Adds a new fragment to the uri_builder.
+ * \param fragment The fragment.
+ * \returns \c *this
+ */
+ template <typename Source>
+ uri_builder &fragment(const Source &fragment) {
+ set_fragment(detail::translate(fragment));
+ return *this;
+ }
+
+ /**
+ * \brief Clears the URI fragment part.
+ * \returns \c *this
+ */
+ uri_builder &clear_fragment();
+
+ /**
+ * \brief Builds a new uri object.
+ * \returns A valid uri object.
+ * \throws uri_builder_error if the uri_builder is unable to build
+ * a valid URI.
+ * \throws std::bad_alloc If the underlying string cannot be
+ * allocated.
+ */
+ network::uri uri() const;
+
+ private:
+ void set_scheme(string_type &&scheme);
+ void set_user_info(string_type &&user_info);
+ void set_host(string_type &&host);
+ void set_port(string_type &&port);
+ void set_authority(string_type &&authority);
+ void set_path(string_type &&path);
+ void append_query_component(string_type &&name);
+ void append_query_key_value_pair(string_type &&key, string_type &&value);
+ void set_fragment(string_type &&fragment);
+
+ optional<string_type> scheme_, user_info_, host_, port_, path_, query_,
+ fragment_;
+};
+} // namespace network
+
+#ifdef NETWORK_URI_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // NETWORK_URI_BUILDER_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/uri_errors.cpp b/graphics/asymptote/LspCpp/network/uri/uri_errors.cpp
new file mode 100644
index 0000000000..b718cff586
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri_errors.cpp
@@ -0,0 +1,72 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <string>
+#include <network/uri/uri_errors.hpp>
+
+namespace network {
+
+ class uri_category_impl : public std::error_category {
+
+ public:
+
+ uri_category_impl() = default;
+
+ virtual ~uri_category_impl() noexcept;
+
+ virtual const char *name() const noexcept;
+
+ virtual std::string message(int ev) const;
+
+ };
+
+ uri_category_impl::~uri_category_impl() noexcept {}
+
+ const char *uri_category_impl::name() const noexcept {
+ static const char name[] = "uri_error";
+ return name;
+ }
+
+ std::string uri_category_impl::message(int ev) const {
+ switch (uri_error(ev)) {
+ case uri_error::invalid_syntax:
+ return "Unable to parse URI string.";
+ case uri_error::not_enough_input:
+ return "Percent decoding: Not enough input.";
+ case uri_error::non_hex_input:
+ return "Percent decoding: Non-hex input.";
+ case uri_error::conversion_failed:
+ return "Percent decoding: Conversion failed.";
+ default:
+ break;
+ }
+ return "Unknown URI error.";
+ }
+
+ const std::error_category &uri_category() {
+ static uri_category_impl uri_category;
+ return uri_category;
+ }
+
+ std::error_code make_error_code(uri_error e) {
+ return std::error_code(static_cast<int>(e), uri_category());
+ }
+
+ uri_syntax_error::uri_syntax_error()
+ : std::system_error(make_error_code(uri_error::invalid_syntax)) {}
+
+ uri_syntax_error::~uri_syntax_error() noexcept {}
+
+ uri_builder_error::uri_builder_error()
+ : std::system_error(make_error_code(uri_error::invalid_uri)) {}
+
+ uri_builder_error::~uri_builder_error() noexcept {}
+
+ percent_decoding_error::percent_decoding_error(uri_error error)
+ : std::system_error(make_error_code(error)) {}
+
+ percent_decoding_error::~percent_decoding_error() noexcept {}
+
+} // namespace network
diff --git a/graphics/asymptote/LspCpp/network/uri/uri_errors.hpp b/graphics/asymptote/LspCpp/network/uri/uri_errors.hpp
new file mode 100644
index 0000000000..a192533dfd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri_errors.hpp
@@ -0,0 +1,122 @@
+// Copyright 2013-2016 Glyn Matthews.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NETWORK_URI_ERRORS_INC
+#define NETWORK_URI_ERRORS_INC
+
+/**
+ * \file
+ * \brief Contains functions and exceptions for URI error handling.
+ */
+
+#include <system_error>
+#include <network/uri/config.hpp>
+
+#ifdef NETWORK_URI_MSVC
+# pragma warning(push)
+# pragma warning(disable : 4251 4231 4660)
+ // Disable C4275 too because it's "essentially noise and can be silenced"
+ // according to Stephen T. Lavavej at Microsoft. See:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/696593/vc-10-vs-2010-basic-string-exports.
+# pragma warning(disable : 4275)
+#endif
+
+namespace network {
+
+#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
+ enum class uri_error {
+
+ // parser errors
+ invalid_syntax = 1,
+
+ // builder errors
+ invalid_uri,
+ invalid_scheme,
+ invalid_user_info,
+ invalid_host,
+ invalid_port,
+ invalid_path,
+ invalid_query,
+ invalid_fragment,
+
+ // encoding errors
+ not_enough_input,
+ non_hex_input,
+ conversion_failed,
+ };
+
+ const std::error_category &uri_category();
+
+ std::error_code make_error_code(uri_error e);
+#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ /**
+ * \class uri_syntax_error uri.hpp network/uri.hpp
+ * \brief An exception thrown by the \c uri constructor when a URI
+ * cannot be parsed.
+ */
+ class uri_syntax_error : public std::system_error {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ uri_syntax_error();
+
+ /**
+ * \brief Destructor.
+ */
+ virtual ~uri_syntax_error() noexcept;
+
+ };
+
+ /**
+ * \class uri_builder_error uri.hpp network/uri.hpp
+ * \brief An exception thrown when the \c uri_builder cannot build a
+ * valid URI.
+ */
+ class uri_builder_error : public std::system_error {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ uri_builder_error();
+
+ /**
+ * \brief Destructor.
+ */
+ virtual ~uri_builder_error() noexcept;
+
+ };
+
+ /**
+ * \class percent_decoding_error uri.hpp network/uri.hpp
+ * \brief An exception thrown when during percent decoding.
+ */
+ class percent_decoding_error : public std::system_error {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ explicit percent_decoding_error(uri_error error);
+
+ /**
+ * \brief Destructor.
+ */
+ virtual ~percent_decoding_error() noexcept;
+
+ };
+} // namespace network
+
+#ifdef NETWORK_URI_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // NETWORK_URI_ERRORS_INC
diff --git a/graphics/asymptote/LspCpp/network/uri/uri_io.hpp b/graphics/asymptote/LspCpp/network/uri/uri_io.hpp
new file mode 100644
index 0000000000..cb9b243f43
--- /dev/null
+++ b/graphics/asymptote/LspCpp/network/uri/uri_io.hpp
@@ -0,0 +1,62 @@
+// Copyright (c) Glyn Matthews 2011-2016
+// Copyright 2012 Dean Michael Berris <dberris@google.com>
+// Copyright 2012 Google, Inc.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file
+ * \brief Defines stream overloads for the uri class.
+ */
+
+#ifndef NETWORK_URI_URI_IO_INC
+#define NETWORK_URI_URI_IO_INC
+
+#include <network/uri/config.hpp>
+#include <network/uri/uri.hpp>
+#include <iosfwd>
+
+namespace network {
+#if !defined(NETWORK_URI_MSVC)
+template <typename CharT, class CharTraits = std::char_traits<CharT> >
+std::basic_ostream<CharT, CharTraits> &operator<<(
+ std::basic_ostream<CharT, CharTraits> &os, const uri &uri_) {
+ return os << uri_.to_string<CharT, CharTraits>();
+}
+
+template <typename CharT, class CharTraits = std::char_traits<CharT> >
+std::basic_istream<CharT, CharTraits> &operator>>(
+ std::basic_istream<CharT, CharTraits> &is, uri &uri_) {
+ std::basic_string<CharT, CharTraits> uri_string;
+ is >> uri_string;
+ uri_ = uri(uri_string);
+ return is;
+}
+#else
+inline std::ostream &operator<<(std::ostream &os, const uri &uri_) {
+ return os << uri_.string();
+}
+
+inline std::wostream &operator<<(std::wostream &os, const uri &uri_) {
+ return os << uri_.wstring();
+}
+
+inline std::istream &operator>>(std::istream &is, uri &uri_) {
+ std::string uri_string;
+ is >> uri_string;
+ uri_ = uri(uri_string);
+ return is;
+}
+
+inline std::wistream &operator>>(std::wistream &is, uri &uri_) {
+ std::wstring uri_string;
+ is >> uri_string;
+ uri_ = uri(uri_string);
+ return is;
+}
+#endif // !defined(NETWORK_URI_MSVC)
+
+} // namespace network
+
+#endif // NETWORK_URI_URI_IO_INC
diff --git a/graphics/asymptote/LspCpp/packages.config b/graphics/asymptote/LspCpp/packages.config
new file mode 100644
index 0000000000..f4caf6a09e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/packages.config
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="boost" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_chrono-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_context-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_coroutine-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_date_time-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_filesystem-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_program_options-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_regex-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_system-vc140" version="1.76.0.0" targetFramework="native" />
+ <package id="boost_thread-vc141" version="1.76.0.0" targetFramework="native" />
+ <package id="tencent.rapidjson" version="1.1.1" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG b/graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG
new file mode 100644
index 0000000000..635fbcfde5
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG
@@ -0,0 +1,88 @@
+Change Log
+
+0.2.5
+ - Made threadpool compatible to boost::thread 1.37
+ - Fixed hang problem in shutdown method (Thanks to Sohail Somani)
+ - Adapted repository layout to boost (Thanks to Alex Ott)
+
+0.2.4 (Stable)
+ - Made threadpool compatible to boost::thread 1.35.x code base
+ - Fixed compiler warning in scope_guard.hpp
+
+0.2.3 (Development)
+ - Implemented workaround for Sun C++ Pro compiler bug in pool_core
+ - Removed subtask implementation (there was no demand for this feature)
+ - Improved shutdown policies
+
+0.2.2 (Development)
+ - Refactored SizePolicy and added SizePolicyController
+ - Moved policies into separate files
+ - Fixed some compiler problems (GCC)
+ - Implemented size_controller handling
+ - Implemented two size policies: static_size and fixed_size
+ - Refactored worker_thread handling, moved policies from pool_core to pool
+ - Specialized schedule function for usage with futures
+ - Added compile test project
+ - Improved constness in pool core class
+ - Fixed timed wait
+ - Implemented futures (in progress)
+ - Added result_type to all functors
+
+0.2.1 (Development)
+ - Pool base class (thread_pool) has now reference semantics
+ - Large refactorings: Removed scoped_pool, reimplemented worker (now worker_thread)
+ - Fixed odd resize behaviour. Now resize changes the number of threads immediately
+ - Apply pimpl idiom on pool core class (to make the ugly scoped_pool class needless)
+ - Introduced scheduling policies
+ - Switched to policy-based design (PBD), inspired by Scott Meyers C++ workshop
+ - Cosmetic code change: Replaced keyword 'class' with 'typename' in template definitions
+ - Revised tutorials
+ - New requirements: tasks functions should not and schedulers shall not throw exceptions
+
+
+0.2.0 (Development)
+ - Moved threadpool into the boost namespace: boost::threadpool
+ - Used keyword volatile to indicate thread-safe member functions
+ - Used volatile on primitve types were appropriate
+ - Moved worker to detail directory
+ - Fixed thread deletion
+ - Extended wait functionality (waiting for idle threads was implemented)
+ - Renamed 'join()' to 'wait()' as 'join' indicates the termination of thread. That was not the case in pool::join.
+ - Changed internal container of lifo and fifo schedulers to improve efficiency.
+ - Improved code reference documentation (source code browser)
+ - Renamed thread_func into task_func
+ - Added += operator to scoped_pool to ease scheduling of tasks
+ - Refactored file structures and class names
+ - Added a new task concept (named subtask) which allows the combination of sequential and parallel execution
+ - Added new task adaptor for looped or timed tasks: looped_task_func
+ - Introduced function clear() which can be used to remove all tasks from the pool and schedulers
+ - New function pool::active() which returns the number of active tasks
+
+0.1.8 (Development)
+ - Fixed some compile errors which were reported by gcc
+ - Wrote tutorial "Prioritized Tasks"
+
+0.1.7 (Development)
+ - Added Visual Studio 2005 project files for tutorial and examples
+
+0.1.6 (Development)
+ - Replaced task adaptor 'task' with boost::bind
+ - Workers are unregistered from thread_group when they are terminated
+ - Working on example boost::iostreams packet_filter
+
+0.1.5 (Development)
+ - Finished threadpool reference
+ - Class pool_adaptor was replaced by smart_pool
+ - Minor pool improvements
+ - First tutorial page online
+
+0.1.4 (Development)
+ - Created the pool's homepage: http://threadpool.sourceforge.net
+ - Improved documentation
+ - Added build scripts
+
+0.1.3 (Development)
+ - First public release
+ - Added mergesort example
+ - Added tutorial
+ - Implementation of threadpool core and related classes \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/COPYING b/graphics/asymptote/LspCpp/third_party/threadpool/COPYING
new file mode 100644
index 0000000000..06bdc4605a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/COPYING
@@ -0,0 +1,5 @@
+Copyright (c) 2005-2007 Philipp Henkel
+
+Use, modification, and distribution are subject to the
+Boost Software License, Version 1.0. (See accompanying file
+LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v2
new file mode 100644
index 0000000000..56c8549755
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v2
@@ -0,0 +1,13 @@
+use-project /boost
+ : $(BOOST_ROOT)
+ ;
+
+project threadpool
+ : requirements <include>.&&$(BOOST_ROOT)
+ # disable auto-linking for all targets here,
+ # primarily because it caused troubles with V2
+ <define>BOOST_ALL_NO_LIB=1
+ : usage-requirements <include>.&&$(BOOST_ROOT)
+ : build-dir bin.v2
+ ;
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/Jamrules b/graphics/asymptote/LspCpp/third_party/threadpool/Jamrules
new file mode 100644
index 0000000000..8571a1461c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/Jamrules
@@ -0,0 +1 @@
+project boost : $(BOOST_ROOT) ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt b/graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/Makefile b/graphics/asymptote/LspCpp/third_party/threadpool/Makefile
new file mode 100644
index 0000000000..9acf23b272
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/Makefile
@@ -0,0 +1,32 @@
+export RELEASE_MANAGER=philipphenkel
+export RELEASE_VERSION=0_2_5
+
+doc: clean
+ make --directory=./libs/threadpool/doc --print-directory doc
+
+release_doc:
+ make --directory=./libs/threadpool/doc --print-directory release_doc
+
+release_src: clean fetch_clean_src
+ mv clean_src threadpool-$(RELEASE_VERSION)-src
+ zip -r9 threadpool-$(RELEASE_VERSION)-src.zip threadpool-$(RELEASE_VERSION)-src
+ rm -rf threadpool-$(RELEASE_VERSION)-src
+
+deploy_website:
+ make --directory=./libs/threadpool/doc --print-directory deploy_sf
+
+clean:
+ rm -rf clean_src
+ rm -rf threadpool-$(RELEASE_VERSION)-src.zip
+ rm -rf threadpool-$(RELEASE_VERSION)-doc.zip
+ make --directory=./libs/threadpool/doc --print-directory clean
+
+fetch_clean_src:
+ rm -rf clean_src
+ mkdir clean_src
+# cvs -d:pserver:anonymous@threadpool.cvs.sourceforge.net:/cvsroot/threadpool login
+ cd clean_src; cvs -z3 -d:pserver:anonymous@threadpool.cvs.sourceforge.net:/cvsroot/threadpool export -r RELEASE_$(RELEASE_VERSION) threadpool
+# cd clean_src; cvs -z3 -d:ext:$(RELEASE_MANAGER)@cvs.sourceforge.net:/cvsroot/threadpool export -r RELEASE_$(RELEASE_VERSION) threadpool
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/README b/graphics/asymptote/LspCpp/third_party/threadpool/README
new file mode 100644
index 0000000000..c6f1a83d81
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/README
@@ -0,0 +1,10 @@
+threadpool
+
+Copyright (c) 2005-2007 Philipp Henkel
+
+threadpool is a cross-platform C++ thread pool library and released under the Boost Software License.
+
+See doc/index.html for information on:
+ - API documentation and a tutorial
+ - External dependencies
+ - Using threadpool
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/TODO b/graphics/asymptote/LspCpp/third_party/threadpool/TODO
new file mode 100644
index 0000000000..1c5e6e26d6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/TODO
@@ -0,0 +1,36 @@
+threadpool to-do items
+======================
+
+Documentation
+--------------------------------------------
+- Source code documentation
+- Design rationale
+- Tutorial
+- Finish Quickstart Tutorial/Example
+
+Functionality
+--------------------------------------------
+- Implement a size policy which dynamically
+ increase/decrease the pool's size:
+ - init with min/max threads
+ - auto increase
+ - auto decrease (using timed cleanup tasks)
+- Add some kind of deadline scheduler
+- Add futures to pool
+
+
+Examples
+--------------------------------------------
+- Buffering Client Requests: Handle 'bursty' client traffic
+ Some applications need more buffering than is provided by OS I/O subsystem
+
+ Working on 'active' buffer for boost::iostreams
+ buffer_filter which provides a dynamic amount of buffer objects.
+ buffer_filter uses a threadpool with one thread which provides the buffers to
+ consumer. (TODO Philipp)
+
+ 2nd implemention step:
+ Flexbile configuration: Buffer capacities can be configured according to
+ - maximum number of requests
+ - maximum number of bytes
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp
new file mode 100644
index 0000000000..7d9ee48010
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp
@@ -0,0 +1,28 @@
+/*! \file
+* \brief Main include.
+*
+* This is the only file you have to include in order to use the
+* complete threadpool library.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+#ifndef THREADPOOL_HPP_INCLUDED
+#define THREADPOOL_HPP_INCLUDED
+
+#include "./threadpool/future.hpp"
+#include "./threadpool/pool.hpp"
+
+#include "./threadpool/pool_adaptors.hpp"
+#include "./threadpool/task_adaptors.hpp"
+
+
+#endif // THREADPOOL_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp
new file mode 100644
index 0000000000..4e4b35bebe
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp
@@ -0,0 +1,215 @@
+/*! \file
+* \brief TODO.
+*
+* TODO.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED
+#define THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED
+
+
+#include "locking_ptr.hpp"
+
+#include <boost/smart_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+template<class Result>
+class future_impl
+{
+public:
+ typedef Result const & result_type; //!< Indicates the functor's result type.
+
+ typedef Result future_result_type; //!< Indicates the future's result type.
+ typedef future_impl<future_result_type> future_type;
+
+private:
+ volatile bool m_ready;
+ volatile future_result_type m_result;
+
+ mutable mutex m_monitor;
+ mutable condition m_condition_ready;
+
+ volatile bool m_is_cancelled;
+ volatile bool m_executing;
+
+public:
+
+
+public:
+
+ future_impl()
+ : m_ready(false)
+ , m_is_cancelled(false)
+ {
+ }
+
+ bool ready() const volatile
+ {
+ return m_ready;
+ }
+
+ void wait() const volatile
+ {
+ const future_type* self = const_cast<const future_type*>(this);
+ mutex::scoped_lock lock(self->m_monitor);
+
+ while(!m_ready)
+ {
+ self->m_condition_ready.wait(lock);
+ }
+ }
+
+
+ bool timed_wait(boost::xtime const & timestamp) const
+ {
+ const future_type* self = const_cast<const future_type*>(this);
+ mutex::scoped_lock lock(self->m_monitor);
+
+ while(!m_ready)
+ {
+ if(!self->m_condition_ready.timed_wait(lock, timestamp)) return false;
+ }
+
+ return true;
+ }
+
+
+ result_type operator()() const volatile
+ {
+ wait();
+/*
+ if( throw_exception_ != 0 )
+ {
+ throw_exception_( this );
+ }
+*/
+
+ return *(const_cast<const future_result_type*>(&m_result));
+ }
+
+
+ void set_value(future_result_type const & r) volatile
+ {
+ locking_ptr<future_type, mutex> lockedThis(*this, m_monitor);
+ if(!m_ready && !m_is_cancelled)
+ {
+ lockedThis->m_result = r;
+ lockedThis->m_ready = true;
+ lockedThis->m_condition_ready.notify_all();
+ }
+ }
+/*
+ template<class E> void set_exception() // throw()
+ {
+ m_impl->template set_exception<E>();
+ }
+
+ template<class E> void set_exception( char const * what ) // throw()
+ {
+ m_impl->template set_exception<E>( what );
+ }
+ */
+
+
+ bool cancel() volatile
+ {
+ if(!m_ready || m_executing)
+ {
+ m_is_cancelled = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ bool is_cancelled() const volatile
+ {
+ return m_is_cancelled;
+ }
+
+
+ void set_execution_status(bool executing) volatile
+ {
+ m_executing = executing;
+ }
+};
+
+
+template<
+ template <typename> class Future,
+ typename Function
+>
+class future_impl_task_func
+{
+
+public:
+ typedef void result_type; //!< Indicates the functor's result type.
+
+ typedef Function function_type; //!< Indicates the function's type.
+ typedef typename result_of<function_type()>::type future_result_type; //!< Indicates the future's result type.
+ typedef Future<future_result_type> future_type; //!< Indicates the future's type.
+
+ // The task is required to be a nullary function.
+ BOOST_STATIC_ASSERT(function_traits<function_type()>::arity == 0);
+
+ // The task function's result type is required not to be void.
+ BOOST_STATIC_ASSERT(!is_void<future_result_type>::value);
+
+private:
+ function_type m_function;
+ shared_ptr<future_type> m_future;
+
+public:
+ future_impl_task_func(function_type const & function, shared_ptr<future_type> const & future)
+ : m_function(function)
+ , m_future(future)
+ {
+ }
+
+ void operator()()
+ {
+ if(m_function)
+ {
+ m_future->set_execution_status(true);
+ if(!m_future->is_cancelled())
+ {
+ // TODO future exeception handling
+ m_future->set_value(m_function());
+ }
+ m_future->set_execution_status(false); // TODO consider exceptions
+ }
+ }
+
+};
+
+
+
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp
new file mode 100644
index 0000000000..57ba560b5a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp
@@ -0,0 +1,85 @@
+/*! \file
+* \brief The locking_ptr is smart pointer with a scoped locking mechanism.
+*
+* The class is a wrapper for a volatile pointer. It enables synchronized access to the
+* internal pointer by locking the passed mutex.
+* locking_ptr is based on Andrei Alexandrescu's LockingPtr. For more information
+* see article "volatile - Multithreaded Programmer's Best Friend" by A. Alexandrescu.
+*
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED
+#define THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED
+
+#include <boost/utility.hpp>
+#include <boost/thread/mutex.hpp>
+
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+/*! \brief Smart pointer with a scoped locking mechanism.
+ *
+ * This class is a wrapper for a volatile pointer. It enables synchronized access to the
+ * internal pointer by locking the passed mutex.
+ */
+ template <typename T, typename Mutex>
+ class locking_ptr
+ : private noncopyable
+ {
+ T* m_obj; //!< The instance pointer.
+ Mutex & m_mutex; //!< Mutex is used for scoped locking.
+
+ public:
+ /// Constructor.
+ locking_ptr(volatile T& obj, const volatile Mutex& mtx)
+ : m_obj(const_cast<T*>(&obj))
+ , m_mutex(*const_cast<Mutex*>(&mtx))
+ {
+ // Lock mutex
+ m_mutex.lock();
+ }
+
+
+ /// Destructor.
+ ~locking_ptr()
+ {
+ // Unlock mutex
+ m_mutex.unlock();
+ }
+
+
+ /*! Returns a reference to the stored instance.
+ * \return The instance's reference.
+ */
+ T& operator*() const
+ {
+ return *m_obj;
+ }
+
+
+ /*! Returns a pointer to the stored instance.
+ * \return The instance's pointer.
+ */
+ T* operator->() const
+ {
+ return m_obj;
+ }
+ };
+
+
+} } } // namespace boost::threadpool::detail
+
+
+#endif // THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp
new file mode 100644
index 0000000000..a81df87763
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp
@@ -0,0 +1,453 @@
+/*! \file
+* \brief Thread pool core.
+*
+* This file contains the threadpool's core class: pool<Task, SchedulingPolicy>.
+*
+* Thread pools are a mechanism for asynchronous and parallel processing
+* within the same process. The pool class provides a convenient way
+* for dispatching asynchronous tasks as functions objects. The scheduling
+* of these tasks can be easily controlled by using customized schedulers.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_POOL_CORE_HPP_INCLUDED
+#define THREADPOOL_POOL_CORE_HPP_INCLUDED
+
+
+
+
+#include "locking_ptr.hpp"
+#include "worker_thread.hpp"
+
+#include "../task_adaptors.hpp"
+
+#include <boost/thread.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/smart_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+#include <vector>
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool { namespace detail
+{
+
+ /*! \brief Thread pool.
+ *
+ * Thread pools are a mechanism for asynchronous and parallel processing
+ * within the same process. The pool class provides a convenient way
+ * for dispatching asynchronous tasks as functions objects. The scheduling
+ * of these tasks can be easily controlled by using customized schedulers.
+ * A task must not throw an exception.
+ *
+ * A pool_impl is DefaultConstructible and NonCopyable.
+ *
+ * \param Task A function object which implements the operator 'void operator() (void) const'. The operator () is called by the pool to execute the task. Exceptions are ignored.
+ * \param Scheduler A task container which determines how tasks are scheduled. It is guaranteed that this container is accessed only by one thread at a time. The scheduler shall not throw exceptions.
+ *
+ * \remarks The pool class is thread-safe.
+ *
+ * \see Tasks: task_func, prio_task_func
+ * \see Scheduling policies: fifo_scheduler, lifo_scheduler, prio_scheduler
+ */
+ template <
+ typename Task,
+
+ template <typename> class SchedulingPolicy,
+ template <typename> class SizePolicy,
+ template <typename> class SizePolicyController,
+ template <typename> class ShutdownPolicy
+ >
+ class pool_core
+ : public enable_shared_from_this< pool_core<Task, SchedulingPolicy, SizePolicy, SizePolicyController, ShutdownPolicy > >
+ , private noncopyable
+ {
+
+ public: // Type definitions
+ typedef Task task_type; //!< Indicates the task's type.
+ typedef SchedulingPolicy<task_type> scheduler_type; //!< Indicates the scheduler's type.
+ typedef pool_core<Task,
+ SchedulingPolicy,
+ SizePolicy,
+ SizePolicyController,
+ ShutdownPolicy > pool_type; //!< Indicates the thread pool's type.
+ typedef SizePolicy<pool_type> size_policy_type; //!< Indicates the sizer's type.
+ //typedef typename size_policy_type::size_controller size_controller_type;
+
+ typedef SizePolicyController<pool_type> size_controller_type;
+
+// typedef SizePolicy<pool_type>::size_controller size_controller_type;
+ typedef ShutdownPolicy<pool_type> shutdown_policy_type;//!< Indicates the shutdown policy's type.
+
+ typedef worker_thread<pool_type> worker_type;
+
+ // The task is required to be a nullary function.
+ BOOST_STATIC_ASSERT(function_traits<task_type()>::arity == 0);
+
+ // The task function's result type is required to be void.
+ BOOST_STATIC_ASSERT(is_void<typename result_of<task_type()>::type >::value);
+
+
+ private: // Friends
+ friend class worker_thread<pool_type>;
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x580) // Tested with CC: Sun C++ 5.8 Patch 121018-08 2006/12/06
+ friend class SizePolicy;
+ friend class ShutdownPolicy;
+#else
+ friend class SizePolicy<pool_type>;
+ friend class ShutdownPolicy<pool_type>;
+#endif
+
+ private: // The following members may be accessed by _multiple_ threads at the same time:
+ volatile size_t m_worker_count;
+ volatile size_t m_target_worker_count;
+ volatile size_t m_active_worker_count;
+
+
+
+ private: // The following members are accessed only by _one_ thread at the same time:
+ scheduler_type m_scheduler;
+ scoped_ptr<size_policy_type> m_size_policy; // is never null
+
+ bool m_terminate_all_workers; // Indicates if termination of all workers was triggered.
+ std::vector<shared_ptr<worker_type> > m_terminated_workers; // List of workers which are terminated but not fully destructed.
+
+ private: // The following members are implemented thread-safe:
+ mutable recursive_mutex m_monitor;
+ mutable condition m_worker_idle_or_terminated_event; // A worker is idle or was terminated.
+ mutable condition m_task_or_terminate_workers_event; // Task is available OR total worker count should be reduced.
+
+ public:
+ /// Constructor.
+ pool_core()
+ : m_worker_count(0)
+ , m_target_worker_count(0)
+ , m_active_worker_count(0)
+ , m_terminate_all_workers(false)
+ {
+ pool_type volatile & self_ref = *this;
+ m_size_policy.reset(new size_policy_type(self_ref));
+
+ m_scheduler.clear();
+ }
+
+
+ /// Destructor.
+ ~pool_core()
+ {
+ }
+
+ /*! Gets the size controller which manages the number of threads in the pool.
+ * \return The size controller.
+ * \see SizePolicy
+ */
+ size_controller_type size_controller()
+ {
+ return size_controller_type(*m_size_policy, this->shared_from_this());
+ }
+
+ /*! Gets the number of threads in the pool.
+ * \return The number of threads.
+ */
+ size_t size() const volatile
+ {
+ return m_worker_count;
+ }
+
+// TODO is only called once
+ void shutdown()
+ {
+ ShutdownPolicy<pool_type>::shutdown(*this);
+ }
+
+ /*! Schedules a task for asynchronous execution. The task will be executed once only.
+ * \param task The task function object. It should not throw execeptions.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool schedule(task_type const & task) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+
+ if(lockedThis->m_scheduler.push(task))
+ {
+ lockedThis->m_task_or_terminate_workers_event.notify_one();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ /*! Returns the number of tasks which are currently executed.
+ * \return The number of active tasks.
+ */
+ size_t active() const volatile
+ {
+ return m_active_worker_count;
+ }
+
+
+ /*! Returns the number of tasks which are ready for execution.
+ * \return The number of pending tasks.
+ */
+ size_t pending() const volatile
+ {
+ locking_ptr<const pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ return lockedThis->m_scheduler.size();
+ }
+
+
+ /*! Removes all pending tasks from the pool's scheduler.
+ */
+ void clear() volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ lockedThis->m_scheduler.clear();
+ }
+
+
+ /*! Indicates that there are no tasks pending.
+ * \return true if there are no tasks ready for execution.
+ * \remarks This function is more efficient that the check 'pending() == 0'.
+ */
+ bool empty() const volatile
+ {
+ locking_ptr<const pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ return lockedThis->m_scheduler.empty();
+ }
+
+
+ /*! The current thread of execution is blocked until the sum of all active
+ * and pending tasks is equal or less than a given threshold.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ */
+ void wait(size_t const task_threshold = 0) const volatile
+ {
+ const pool_type* self = const_cast<const pool_type*>(this);
+ recursive_mutex::scoped_lock lock(self->m_monitor);
+
+ if(0 == task_threshold)
+ {
+ while(0 != self->m_active_worker_count || !self->m_scheduler.empty())
+ {
+ self->m_worker_idle_or_terminated_event.wait(lock);
+ }
+ }
+ else
+ {
+ while(task_threshold < self->m_active_worker_count + self->m_scheduler.size())
+ {
+ self->m_worker_idle_or_terminated_event.wait(lock);
+ }
+ }
+ }
+
+ /*! The current thread of execution is blocked until the timestamp is met
+ * or the sum of all active and pending tasks is equal or less
+ * than a given threshold.
+ * \param timestamp The time when function returns at the latest.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ * \return true if the task sum is equal or less than the threshold, false otherwise.
+ */
+ bool wait(xtime const & timestamp, size_t const task_threshold = 0) const volatile
+ {
+ const pool_type* self = const_cast<const pool_type*>(this);
+ recursive_mutex::scoped_lock lock(self->m_monitor);
+
+ if(0 == task_threshold)
+ {
+ while(0 != self->m_active_worker_count || !self->m_scheduler.empty())
+ {
+ if(!self->m_worker_idle_or_terminated_event.timed_wait(lock, timestamp)) return false;
+ }
+ }
+ else
+ {
+ while(task_threshold < self->m_active_worker_count + self->m_scheduler.size())
+ {
+ if(!self->m_worker_idle_or_terminated_event.timed_wait(lock, timestamp)) return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ private:
+
+
+ void terminate_all_workers(bool const wait) volatile
+ {
+ pool_type* self = const_cast<pool_type*>(this);
+ recursive_mutex::scoped_lock lock(self->m_monitor);
+
+ self->m_terminate_all_workers = true;
+
+ m_target_worker_count = 0;
+ self->m_task_or_terminate_workers_event.notify_all();
+
+ if(wait)
+ {
+ while(m_active_worker_count > 0)
+ {
+ self->m_worker_idle_or_terminated_event.wait(lock);
+ }
+
+ for(typename std::vector<shared_ptr<worker_type> >::iterator it = self->m_terminated_workers.begin();
+ it != self->m_terminated_workers.end();
+ ++it)
+ {
+ (*it)->join();
+ }
+ self->m_terminated_workers.clear();
+ }
+ }
+
+
+ /*! Changes the number of worker threads in the pool. The resizing
+ * is handled by the SizePolicy.
+ * \param threads The new number of worker threads.
+ * \return true, if pool will be resized and false if not.
+ */
+ bool resize(size_t const worker_count) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+
+ if(!m_terminate_all_workers)
+ {
+ m_target_worker_count = worker_count;
+ }
+ else
+ {
+ return false;
+ }
+
+
+ if(m_worker_count <= m_target_worker_count)
+ { // increase worker count
+ while(m_worker_count < m_target_worker_count)
+ {
+ try
+ {
+ worker_thread<pool_type>::create_and_attach(lockedThis->shared_from_this());
+ m_worker_count++;
+ m_active_worker_count++;
+ }
+ catch(thread_resource_error&)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ { // decrease worker count
+ lockedThis->m_task_or_terminate_workers_event.notify_all(); // TODO: Optimize number of notified workers
+ }
+
+ return true;
+ }
+
+
+ // worker died with unhandled exception
+ void worker_died_unexpectedly(shared_ptr<worker_type> worker) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+
+ m_worker_count--;
+ m_active_worker_count--;
+ lockedThis->m_worker_idle_or_terminated_event.notify_all();
+
+ if(m_terminate_all_workers)
+ {
+ lockedThis->m_terminated_workers.push_back(worker);
+ }
+ else
+ {
+ lockedThis->m_size_policy->worker_died_unexpectedly(m_worker_count);
+ }
+ }
+
+ void worker_destructed(shared_ptr<worker_type> worker) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ m_worker_count--;
+ m_active_worker_count--;
+ lockedThis->m_worker_idle_or_terminated_event.notify_all();
+
+ if(m_terminate_all_workers)
+ {
+ lockedThis->m_terminated_workers.push_back(worker);
+ }
+ }
+
+
+ bool execute_task() volatile
+ {
+ function0<void> task;
+
+ { // fetch task
+ pool_type* lockedThis = const_cast<pool_type*>(this);
+ recursive_mutex::scoped_lock lock(lockedThis->m_monitor);
+
+ // decrease number of threads if necessary
+ if(m_worker_count > m_target_worker_count)
+ {
+ return false; // terminate worker
+ }
+
+
+ // wait for tasks
+ while(lockedThis->m_scheduler.empty())
+ {
+ // decrease number of workers if necessary
+ if(m_worker_count > m_target_worker_count)
+ {
+ return false; // terminate worker
+ }
+ else
+ {
+ m_active_worker_count--;
+ lockedThis->m_worker_idle_or_terminated_event.notify_all();
+ lockedThis->m_task_or_terminate_workers_event.wait(lock);
+ m_active_worker_count++;
+ }
+ }
+
+ task = lockedThis->m_scheduler.top();
+ lockedThis->m_scheduler.pop();
+ }
+
+ // call task function
+ if(task)
+ {
+ task();
+ }
+
+ //guard->disable();
+ return true;
+ }
+ };
+
+
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_POOL_CORE_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp
new file mode 100644
index 0000000000..68634654ba
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp
@@ -0,0 +1,65 @@
+/*! \file
+* \brief TODO.
+*
+* TODO.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED
+#define THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED
+
+
+
+#include <boost/function.hpp>
+
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+// TODO documentation
+class scope_guard
+: private boost::noncopyable
+{
+ function0<void> const m_function;
+ bool m_is_active;
+
+public:
+ scope_guard(function0<void> const & call_on_exit)
+ : m_function(call_on_exit)
+ , m_is_active(true)
+ {
+ }
+
+ ~scope_guard()
+ {
+ if(m_is_active && m_function)
+ {
+ m_function();
+ }
+ }
+
+ void disable()
+ {
+ m_is_active = false;
+ }
+};
+
+
+
+
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp
new file mode 100644
index 0000000000..d33467a527
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp
@@ -0,0 +1,115 @@
+/*! \file
+* \brief Thread pool worker.
+*
+* The worker thread instance is attached to a pool
+* and executes tasks of this pool.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+#ifndef THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED
+#define THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED
+
+
+#include "scope_guard.hpp"
+
+#include <boost/smart_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+ /*! \brief Thread pool worker.
+ *
+ * A worker_thread represents a thread of execution. The worker is attached to a
+ * thread pool and processes tasks of that pool. The lifetime of the worker and its
+ * internal boost::thread is managed automatically.
+ *
+ * This class is a helper class and cannot be constructed or accessed directly.
+ *
+ * \see pool_core
+ */
+ template <typename Pool>
+ class worker_thread
+ : public enable_shared_from_this< worker_thread<Pool> >
+ , private noncopyable
+ {
+ public:
+ typedef Pool pool_type; //!< Indicates the pool's type.
+
+ private:
+ shared_ptr<pool_type> m_pool; //!< Pointer to the pool which created the worker.
+ shared_ptr<boost::thread> m_thread; //!< Pointer to the thread which executes the run loop.
+
+
+ /*! Constructs a new worker.
+ * \param pool Pointer to it's parent pool.
+ * \see function create_and_attach
+ */
+ worker_thread(shared_ptr<pool_type> const & pool)
+ : m_pool(pool)
+ {
+ assert(pool);
+ }
+
+
+ /*! Notifies that an exception occurred in the run loop.
+ */
+ void died_unexpectedly()
+ {
+ m_pool->worker_died_unexpectedly(this->shared_from_this());
+ }
+
+
+ public:
+ /*! Executes pool's tasks sequentially.
+ */
+ void run()
+ {
+ scope_guard notify_exception(bind(&worker_thread::died_unexpectedly, this));
+
+ while(m_pool->execute_task()) {}
+
+ notify_exception.disable();
+ m_pool->worker_destructed(this->shared_from_this());
+ }
+
+
+ /*! Joins the worker's thread.
+ */
+ void join()
+ {
+ m_thread->join();
+ }
+
+
+ /*! Constructs a new worker thread and attaches it to the pool.
+ * \param pool Pointer to the pool.
+ */
+ static void create_and_attach(shared_ptr<pool_type> const & pool)
+ {
+ shared_ptr<worker_thread> worker(new worker_thread(pool));
+ if(worker)
+ {
+ worker->m_thread.reset(new boost::thread(bind(&worker_thread::run, worker)));
+ }
+ }
+
+ };
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp
new file mode 100644
index 0000000000..f4a6e12244
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp
@@ -0,0 +1,144 @@
+/*! \file
+* \brief TODO.
+*
+* TODO.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+#ifndef THREADPOOL_FUTURE_HPP_INCLUDED
+#define THREADPOOL_FUTURE_HPP_INCLUDED
+
+
+
+#include "./detail/future.hpp"
+#include <boost/utility/enable_if.hpp>
+
+//#include "pool.hpp"
+//#include <boost/utility.hpp>
+
+//#include <boost/thread/mutex.hpp>
+
+
+namespace boost { namespace threadpool
+{
+
+ /*! \brief Experimental. Do not use in production code. TODO.
+ *
+ * TODO Future
+ *
+ * \see TODO
+ *
+ */
+
+
+template<class Result>
+class future
+{
+private:
+ shared_ptr<detail::future_impl<Result> > m_impl;
+
+public:
+ typedef Result const & result_type; //!< Indicates the functor's result type.
+ typedef Result future_result_type; //!< Indicates the future's result type.
+
+
+public:
+
+ future()
+ : m_impl(new detail::future_impl<future_result_type>()) // TODO remove this
+ {
+ }
+
+ // only for internal usage
+ future(shared_ptr<detail::future_impl<Result> > const & impl)
+ : m_impl(impl)
+ {
+ }
+
+ bool ready() const
+ {
+ return m_impl->ready();
+ }
+
+ void wait() const
+ {
+ m_impl->wait();
+ }
+
+ bool timed_wait(boost::xtime const & timestamp) const
+ {
+ return m_impl->timed_wait(timestamp);
+ }
+
+ result_type operator()() // throw( thread::cancelation_exception, ... )
+ {
+ return (*m_impl)();
+ }
+
+ result_type get() // throw( thread::cancelation_exception, ... )
+ {
+ return (*m_impl)();
+ }
+
+ bool cancel()
+ {
+ return m_impl->cancel();
+ }
+
+ bool is_cancelled() const
+ {
+ return m_impl->is_cancelled();
+ }
+};
+
+
+
+
+
+template<class Pool, class Function>
+typename disable_if <
+ is_void< typename result_of< Function() >::type >,
+ future< typename result_of< Function() >::type >
+>::type
+schedule(Pool& pool, const Function& task)
+{
+ typedef typename result_of< Function() >::type future_result_type;
+
+ // create future impl and future
+ shared_ptr<detail::future_impl<future_result_type> > impl(new detail::future_impl<future_result_type>);
+ future <future_result_type> res(impl);
+
+ // schedule future impl
+ pool.schedule(detail::future_impl_task_func<detail::future_impl, Function>(task, impl));
+
+ // return future
+ return res;
+
+/*
+ TODO
+ if(pool->schedule(bind(&Future::run, future)))
+ {
+ return future;
+ }
+ else
+ {
+ // construct empty future
+ return error_future;
+ }
+ */
+}
+
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_FUTURE_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp
new file mode 100644
index 0000000000..a4b6676ea9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp
@@ -0,0 +1,232 @@
+/*! \file
+* \brief Thread pool core.
+*
+* This file contains the threadpool's core class: pool<Task, SchedulingPolicy>.
+*
+* Thread pools are a mechanism for asynchronous and parallel processing
+* within the same process. The pool class provides a convenient way
+* for dispatching asynchronous tasks as functions objects. The scheduling
+* of these tasks can be easily controlled by using customized schedulers.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_POOL_HPP_INCLUDED
+#define THREADPOOL_POOL_HPP_INCLUDED
+
+#include <boost/ref.hpp>
+
+#include "./detail/pool_core.hpp"
+
+#include "task_adaptors.hpp"
+
+#include "./detail/locking_ptr.hpp"
+
+#include "scheduling_policies.hpp"
+#include "size_policies.hpp"
+#include "shutdown_policies.hpp"
+
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool
+{
+
+
+
+ /*! \brief Thread pool.
+ *
+ * Thread pools are a mechanism for asynchronous and parallel processing
+ * within the same process. The pool class provides a convenient way
+ * for dispatching asynchronous tasks as functions objects. The scheduling
+ * of these tasks can be easily controlled by using customized schedulers.
+ * A task must not throw an exception.
+ *
+ * A pool is DefaultConstructible, CopyConstructible and Assignable.
+ * It has reference semantics; all copies of the same pool are equivalent and interchangeable.
+ * All operations on a pool except assignment are strongly thread safe or sequentially consistent;
+ * that is, the behavior of concurrent calls is as if the calls have been issued sequentially in an unspecified order.
+ *
+ * \param Task A function object which implements the operator 'void operator() (void) const'. The operator () is called by the pool to execute the task. Exceptions are ignored.
+ * \param SchedulingPolicy A task container which determines how tasks are scheduled. It is guaranteed that this container is accessed only by one thread at a time. The scheduler shall not throw exceptions.
+ *
+ * \remarks The pool class is thread-safe.
+ *
+ * \see Tasks: task_func, prio_task_func
+ * \see Scheduling policies: fifo_scheduler, lifo_scheduler, prio_scheduler
+ */
+ template <
+ typename Task = task_func,
+ template <typename> class SchedulingPolicy = fifo_scheduler,
+ template <typename> class SizePolicy = static_size,
+ template <typename> class SizePolicyController = resize_controller,
+ template <typename> class ShutdownPolicy = wait_for_all_tasks
+ >
+ class thread_pool
+ {
+ typedef detail::pool_core<Task,
+ SchedulingPolicy,
+ SizePolicy,
+ SizePolicyController,
+ ShutdownPolicy> pool_core_type;
+ shared_ptr<pool_core_type> m_core; // pimpl idiom
+ shared_ptr<void> m_shutdown_controller; // If the last pool holding a pointer to the core is deleted the controller shuts the pool down.
+
+ public: // Type definitions
+ typedef Task task_type; //!< Indicates the task's type.
+ typedef SchedulingPolicy<task_type> scheduler_type; //!< Indicates the scheduler's type.
+ /* typedef thread_pool<Task,
+ SchedulingPolicy,
+ SizePolicy,
+ ShutdownPolicy > pool_type; //!< Indicates the thread pool's type.
+ */
+ typedef SizePolicy<pool_core_type> size_policy_type;
+ typedef SizePolicyController<pool_core_type> size_controller_type;
+
+
+ public:
+ /*! Constructor.
+ * \param initial_threads The pool is immediately resized to set the specified number of threads. The pool's actual number threads depends on the SizePolicy.
+ */
+ thread_pool(size_t initial_threads = 0)
+ : m_core(new pool_core_type)
+ , m_shutdown_controller(static_cast<void*>(0), bind(&pool_core_type::shutdown, m_core))
+ {
+ size_policy_type::init(*m_core, initial_threads);
+ }
+
+
+ /*! Gets the size controller which manages the number of threads in the pool.
+ * \return The size controller.
+ * \see SizePolicy
+ */
+ size_controller_type size_controller()
+ {
+ return m_core->size_controller();
+ }
+
+
+ /*! Gets the number of threads in the pool.
+ * \return The number of threads.
+ */
+ size_t size() const
+ {
+ return m_core->size();
+ }
+
+
+ /*! Schedules a task for asynchronous execution. The task will be executed once only.
+ * \param task The task function object. It should not throw execeptions.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool schedule(task_type const & task)
+ {
+ return m_core->schedule(task);
+ }
+
+
+ /*! Returns the number of tasks which are currently executed.
+ * \return The number of active tasks.
+ */
+ size_t active() const
+ {
+ return m_core->active();
+ }
+
+
+ /*! Returns the number of tasks which are ready for execution.
+ * \return The number of pending tasks.
+ */
+ size_t pending() const
+ {
+ return m_core->pending();
+ }
+
+
+ /*! Removes all pending tasks from the pool's scheduler.
+ */
+ void clear()
+ {
+ m_core->clear();
+ }
+
+
+ /*! Indicates that there are no tasks pending.
+ * \return true if there are no tasks ready for execution.
+ * \remarks This function is more efficient that the check 'pending() == 0'.
+ */
+ bool empty() const
+ {
+ return m_core->empty();
+ }
+
+
+ /*! The current thread of execution is blocked until the sum of all active
+ * and pending tasks is equal or less than a given threshold.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ */
+ void wait(size_t task_threshold = 0) const
+ {
+ m_core->wait(task_threshold);
+ }
+
+
+ /*! The current thread of execution is blocked until the timestamp is met
+ * or the sum of all active and pending tasks is equal or less
+ * than a given threshold.
+ * \param timestamp The time when function returns at the latest.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ * \return true if the task sum is equal or less than the threshold, false otherwise.
+ */
+ bool wait(xtime const & timestamp, size_t task_threshold = 0) const
+ {
+ return m_core->wait(timestamp, task_threshold);
+ }
+ };
+
+
+
+ /*! \brief Fifo pool.
+ *
+ * The pool's tasks are fifo scheduled task_func functors.
+ *
+ */
+ typedef thread_pool<task_func, fifo_scheduler, static_size, resize_controller, wait_for_all_tasks> fifo_pool;
+
+
+ /*! \brief Lifo pool.
+ *
+ * The pool's tasks are lifo scheduled task_func functors.
+ *
+ */
+ typedef thread_pool<task_func, lifo_scheduler, static_size, resize_controller, wait_for_all_tasks> lifo_pool;
+
+
+ /*! \brief Pool for prioritized task.
+ *
+ * The pool's tasks are prioritized prio_task_func functors.
+ *
+ */
+ typedef thread_pool<prio_task_func, prio_scheduler, static_size, resize_controller, wait_for_all_tasks> prio_pool;
+
+
+ /*! \brief A standard pool.
+ *
+ * The pool's tasks are fifo scheduled task_func functors.
+ *
+ */
+ typedef fifo_pool pool;
+
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_POOL_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp
new file mode 100644
index 0000000000..6cde152d2a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp
@@ -0,0 +1,70 @@
+/*! \file
+* \brief Pool adaptors.
+*
+* This file contains an easy-to-use adaptor similar to a smart
+* pointer for the pool class.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED
+#define THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED
+
+#include <boost/smart_ptr.hpp>
+
+
+namespace boost { namespace threadpool
+{
+
+
+// TODO convenience scheduling function
+ /*! Schedules a Runnable for asynchronous execution. A Runnable is an arbitrary class with a run()
+ * member function. This a convenience shorthand for pool->schedule(bind(&Runnable::run, task_object)).
+ * \param
+ * \param obj The Runnable object. The member function run() will be exectued and should not throw execeptions.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ template<typename Pool, typename Runnable>
+ bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
+ {
+ return pool->schedule(bind(&Runnable::run, obj));
+ }
+
+ /*! Schedules a task for asynchronous execution. The task will be executed once only.
+ * \param task The task function object.
+ */
+ template<typename Pool>
+ typename enable_if <
+ is_void< typename result_of< typename Pool::task_type() >::type >,
+ bool
+ >::type
+ schedule(Pool& pool, typename Pool::task_type const & task)
+ {
+ return pool.schedule(task);
+ }
+
+
+ template<typename Pool>
+ typename enable_if <
+ is_void< typename result_of< typename Pool::task_type() >::type >,
+ bool
+ >::type
+ schedule(shared_ptr<Pool> const pool, typename Pool::task_type const & task)
+ {
+ return pool->schedule(task);
+ }
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp
new file mode 100644
index 0000000000..2d6c7c1bae
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp
@@ -0,0 +1,262 @@
+/*! \file
+* \brief Task scheduling policies.
+*
+* This file contains some fundamental scheduling policies for the pool class.
+* A scheduling policy is realized by a task container which controls the access to
+* the tasks. Fundamentally the container determines the order the tasks are processed
+* by the thread pool.
+* The task containers need not to be thread-safe because they are used by the pool
+* in thread-safe way.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED
+#define THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED
+
+
+#include <queue>
+#include <deque>
+
+#include "task_adaptors.hpp"
+
+namespace boost { namespace threadpool
+{
+
+ /*! \brief SchedulingPolicy which implements FIFO ordering.
+ *
+ * This container implements a FIFO scheduling policy.
+ * The first task to be added to the scheduler will be the first to be removed.
+ * The processing proceeds sequentially in the same order.
+ * FIFO stands for "first in, first out".
+ *
+ * \param Task A function object which implements the operator()(void).
+ *
+ */
+ template <typename Task = task_func>
+ class fifo_scheduler
+ {
+ public:
+ typedef Task task_type; //!< Indicates the scheduler's task type.
+
+ protected:
+ std::deque<task_type> m_container; //!< Internal task container.
+
+
+ public:
+ /*! Adds a new task to the scheduler.
+ * \param task The task object.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool push(task_type const & task)
+ {
+ m_container.push_back(task);
+ return true;
+ }
+
+ /*! Removes the task which should be executed next.
+ */
+ void pop()
+ {
+ m_container.pop_front();
+ }
+
+ /*! Gets the task which should be executed next.
+ * \return The task object to be executed.
+ */
+ task_type const & top() const
+ {
+ return m_container.front();
+ }
+
+ /*! Gets the current number of tasks in the scheduler.
+ * \return The number of tasks.
+ * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty.
+ */
+ size_t size() const
+ {
+ return m_container.size();
+ }
+
+ /*! Checks if the scheduler is empty.
+ * \return true if the scheduler contains no tasks, false otherwise.
+ * \remarks Is more efficient than size() == 0.
+ */
+ bool empty() const
+ {
+ return m_container.empty();
+ }
+
+ /*! Removes all tasks from the scheduler.
+ */
+ void clear()
+ {
+ m_container.clear();
+ }
+ };
+
+
+
+ /*! \brief SchedulingPolicy which implements LIFO ordering.
+ *
+ * This container implements a LIFO scheduling policy.
+ * The last task to be added to the scheduler will be the first to be removed.
+ * LIFO stands for "last in, first out".
+ *
+ * \param Task A function object which implements the operator()(void).
+ *
+ */
+ template <typename Task = task_func>
+ class lifo_scheduler
+ {
+ public:
+ typedef Task task_type; //!< Indicates the scheduler's task type.
+
+ protected:
+ std::deque<task_type> m_container; //!< Internal task container.
+
+ public:
+ /*! Adds a new task to the scheduler.
+ * \param task The task object.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool push(task_type const & task)
+ {
+ m_container.push_front(task);
+ return true;
+ }
+
+ /*! Removes the task which should be executed next.
+ */
+ void pop()
+ {
+ m_container.pop_front();
+ }
+
+ /*! Gets the task which should be executed next.
+ * \return The task object to be executed.
+ */
+ task_type const & top() const
+ {
+ return m_container.front();
+ }
+
+ /*! Gets the current number of tasks in the scheduler.
+ * \return The number of tasks.
+ * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty.
+ */
+ size_t size() const
+ {
+ return m_container.size();
+ }
+
+ /*! Checks if the scheduler is empty.
+ * \return true if the scheduler contains no tasks, false otherwise.
+ * \remarks Is more efficient than size() == 0.
+ */
+ bool empty() const
+ {
+ return m_container.empty();
+ }
+
+ /*! Removes all tasks from the scheduler.
+ */
+ void clear()
+ {
+ m_container.clear();
+ }
+
+ };
+
+
+
+ /*! \brief SchedulingPolicy which implements prioritized ordering.
+ *
+ * This container implements a scheduling policy based on task priorities.
+ * The task with highest priority will be the first to be removed.
+ * It must be possible to compare two tasks using operator<.
+ *
+ * \param Task A function object which implements the operator() and operator<. operator< must be a partial ordering.
+ *
+ * \see prio_thread_func
+ *
+ */
+ template <typename Task = prio_task_func>
+ class prio_scheduler
+ {
+ public:
+ typedef Task task_type; //!< Indicates the scheduler's task type.
+
+ protected:
+ std::priority_queue<task_type> m_container; //!< Internal task container.
+
+
+ public:
+ /*! Adds a new task to the scheduler.
+ * \param task The task object.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool push(task_type const & task)
+ {
+ m_container.push(task);
+ return true;
+ }
+
+ /*! Removes the task which should be executed next.
+ */
+ void pop()
+ {
+ m_container.pop();
+ }
+
+ /*! Gets the task which should be executed next.
+ * \return The task object to be executed.
+ */
+ task_type const & top() const
+ {
+ return m_container.top();
+ }
+
+ /*! Gets the current number of tasks in the scheduler.
+ * \return The number of tasks.
+ * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty.
+ */
+ size_t size() const
+ {
+ return m_container.size();
+ }
+
+ /*! Checks if the scheduler is empty.
+ * \return true if the scheduler contains no tasks, false otherwise.
+ * \remarks Is more efficient than size() == 0.
+ */
+ bool empty() const
+ {
+ return m_container.empty();
+ }
+
+ /*! Removes all tasks from the scheduler.
+ */
+ void clear()
+ {
+ while(!m_container.empty())
+ {
+ m_container.pop();
+ }
+ }
+ };
+
+
+} } // namespace boost::threadpool
+
+
+#endif // THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp
new file mode 100644
index 0000000000..047a6eb516
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp
@@ -0,0 +1,83 @@
+/*! \file
+* \brief Shutdown policies.
+*
+* This file contains shutdown policies for thread_pool.
+* A shutdown policy controls the pool's behavior from the time
+* when the pool is not referenced any longer.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED
+#define THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED
+
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool
+{
+
+
+/*! \brief ShutdownPolicy which waits for the completion of all tasks
+ * and the worker termination afterwards.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class wait_for_all_tasks
+ {
+ public:
+ static void shutdown(Pool& pool)
+ {
+ pool.wait();
+ pool.terminate_all_workers(true);
+ }
+ };
+
+
+ /*! \brief ShutdownPolicy which waits for the completion of all active tasks
+ * and the worker termination afterwards.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class wait_for_active_tasks
+ {
+ public:
+ static void shutdown(Pool& pool)
+ {
+ pool.clear();
+ pool.wait();
+ pool.terminate_all_workers(true);
+ }
+ };
+
+
+ /*! \brief ShutdownPolicy which does not wait for any tasks or worker termination.
+ *
+ * This policy does not wait for any tasks. Nevertheless all active tasks will be processed completely.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class immediately
+ {
+ public:
+ static void shutdown(Pool& pool)
+ {
+ pool.clear();
+ pool.terminate_all_workers(false);
+ }
+ };
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp
new file mode 100644
index 0000000000..e3c08038db
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp
@@ -0,0 +1,99 @@
+/*! \file
+* \brief Size policies.
+*
+* This file contains size policies for thread_pool. A size
+* policy controls the number of worker threads in the pool.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_SIZE_POLICIES_HPP_INCLUDED
+#define THREADPOOL_SIZE_POLICIES_HPP_INCLUDED
+
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool
+{
+
+ /*! \brief SizePolicyController which provides no functionality.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ struct empty_controller
+ {
+ empty_controller(typename Pool::size_policy_type&, shared_ptr<Pool>) {}
+ };
+
+
+ /*! \brief SizePolicyController which allows resizing.
+ *
+ * \param Pool The pool's core type.
+ */
+ template< typename Pool >
+ class resize_controller
+ {
+ typedef typename Pool::size_policy_type size_policy_type;
+ reference_wrapper<size_policy_type> m_policy;
+ shared_ptr<Pool> m_pool; //!< to make sure that the pool is alive (the policy pointer is valid) as long as the controller exists
+
+ public:
+ resize_controller(size_policy_type& policy, shared_ptr<Pool> pool)
+ : m_policy(policy)
+ , m_pool(pool)
+ {
+ }
+
+ bool resize(size_t worker_count)
+ {
+ return m_policy.get().resize(worker_count);
+ }
+ };
+
+
+ /*! \brief SizePolicy which preserves the thread count.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class static_size
+ {
+ reference_wrapper<Pool volatile> m_pool;
+
+ public:
+ static void init(Pool& pool, size_t const worker_count)
+ {
+ pool.resize(worker_count);
+ }
+
+ static_size(Pool volatile & pool)
+ : m_pool(pool)
+ {}
+
+ bool resize(size_t const worker_count)
+ {
+ return m_pool.get().resize(worker_count);
+ }
+
+ void worker_died_unexpectedly(size_t const new_worker_count)
+ {
+ m_pool.get().resize(new_worker_count + 1);
+ }
+
+ // TODO this functions are not called yet
+ void task_scheduled() {}
+ void task_finished() {}
+ };
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_SIZE_POLICIES_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp
new file mode 100644
index 0000000000..6b874e3358
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp
@@ -0,0 +1,168 @@
+/*! \file
+* \brief Task adaptors.
+*
+* This file contains adaptors for task function objects.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Use, modification, and distribution are subject to the
+* Boost Software License, Version 1.0. (See accompanying file
+* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED
+#define THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED
+
+
+#include <boost/smart_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/thread.hpp>
+
+
+namespace boost { namespace threadpool
+{
+
+ /*! \brief Standard task function object.
+ *
+ * This function object wraps a nullary function which returns void.
+ * The wrapped function is invoked by calling the operator ().
+ *
+ * \see boost function library
+ *
+ */
+ typedef function0<void> task_func;
+
+
+
+
+ /*! \brief Prioritized task function object.
+ *
+ * This function object wraps a task_func object and binds a priority to it.
+ * prio_task_funcs can be compared using the operator < which realises a partial ordering.
+ * The wrapped task function is invoked by calling the operator ().
+ *
+ * \see prio_scheduler
+ *
+ */
+ class prio_task_func
+ {
+ private:
+ unsigned int m_priority; //!< The priority of the task's function.
+ task_func m_function; //!< The task's function.
+
+ public:
+ typedef void result_type; //!< Indicates the functor's result type.
+
+ public:
+ /*! Constructor.
+ * \param priority The priority of the task.
+ * \param function The task's function object.
+ */
+ prio_task_func(unsigned int const priority, task_func const & function)
+ : m_priority(priority)
+ , m_function(function)
+ {
+ }
+
+ /*! Executes the task function.
+ */
+ void operator() (void) const
+ {
+ if(m_function)
+ {
+ m_function();
+ }
+ }
+
+ /*! Comparison operator which realises a partial ordering based on priorities.
+ * \param rhs The object to compare with.
+ * \return true if the priority of *this is less than right hand side's priority, false otherwise.
+ */
+ bool operator< (const prio_task_func& rhs) const
+ {
+ return m_priority < rhs.m_priority;
+ }
+
+ }; // prio_task_func
+
+
+
+
+
+
+
+
+ /*! \brief Looped task function object.
+ *
+ * This function object wraps a boolean thread function object.
+ * The wrapped task function is invoked by calling the operator () and it is executed in regular
+ * time intervals until false is returned. The interval length may be zero.
+ * Please note that a pool's thread is engaged as long as the task is looped.
+ *
+ */
+ class looped_task_func
+ {
+ private:
+ function0<bool> m_function; //!< The task's function.
+ unsigned int m_break_s; //!< Duration of breaks in seconds.
+ unsigned int m_break_ns; //!< Duration of breaks in nano seconds.
+
+ public:
+ typedef void result_type; //!< Indicates the functor's result type.
+
+ public:
+ /*! Constructor.
+ * \param function The task's function object which is looped until false is returned.
+ * \param interval The minimum break time in milli seconds before the first execution of the task function and between the following ones.
+ */
+ looped_task_func(function0<bool> const & function, unsigned int const interval = 0)
+ : m_function(function)
+ {
+ m_break_s = interval / 1000;
+ m_break_ns = (interval - m_break_s * 1000) * 1000 * 1000;
+ }
+
+ /*! Executes the task function.
+ */
+ void operator() (void) const
+ {
+ if(m_function)
+ {
+ if(m_break_s > 0 || m_break_ns > 0)
+ { // Sleep some time before first execution
+ xtime xt;
+ xtime_get(&xt, TIME_UTC);
+ xt.nsec += m_break_ns;
+ xt.sec += m_break_s;
+ thread::sleep(xt);
+ }
+
+ while(m_function())
+ {
+ if(m_break_s > 0 || m_break_ns > 0)
+ {
+ xtime xt;
+ xtime_get(&xt, TIME_UTC);
+ xt.nsec += m_break_ns;
+ xt.sec += m_break_s;
+ thread::sleep(xt);
+ }
+ else
+ {
+ thread::yield(); // Be fair to other threads
+ }
+ }
+ }
+ }
+
+ }; // looped_task_func
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile
new file mode 100644
index 0000000000..578ff7e0ba
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile
@@ -0,0 +1,36 @@
+DOXYGEN=doxygen
+
+doc: clean copy_footer generate_doc
+
+copy_footer:
+ cp footer/*.htm .
+
+copy_footer_sf:
+ cp footer_sf/*.htm .
+
+generate_doc:
+ $(DOXYGEN) overview.dox
+ $(DOXYGEN) reference.dox
+ $(DOXYGEN) tutorial.dox
+ $(DOXYGEN) examples.dox
+ $(DOXYGEN) design.dox
+
+clean:
+ rm -rf ../../../doc
+ rm -rf ../../../threadpool-$(RELEASE_VERSION)-doc
+ rm -rf ../../../threadpool-$(RELEASE_VERSION)-doc.zip
+
+release_doc: clean doc
+ cd ../../..; mv doc threadpool-$(RELEASE_VERSION)-doc
+ cd ../../..; zip -r9 threadpool-$(RELEASE_VERSION)-doc.zip threadpool-$(RELEASE_VERSION)-doc
+ cd ../../..; mv threadpool-$(RELEASE_VERSION)-doc doc
+
+doc_sf: clean copy_footer_sf generate_doc
+
+deploy_sf: doc_sf
+ scp -vr ../../../doc/* $(RELEASE_MANAGER)@shell.sourceforge.net:/home/groups/t/th/threadpool/htdocs
+
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox
new file mode 100644
index 0000000000..06b287c7e4
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/design
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../include/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = design.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = design_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt
new file mode 100644
index 0000000000..05cf85e8ac
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt
@@ -0,0 +1,35 @@
+/*! \page intro TODO5
+
+
+A thread pool manages a homogeneous pool of worker threads. In general worker threads are created once and are used to
+process a sequence of tasks. The re-use of threads reduces the thread creation and teardown overhead. The resource
+consumption is limited as the number of threads can be restricted. This leads to an improved system stability.
+
+Thread-per-task
+
+TODO5
+
+light-weight, no administration/management thread, synchronized scheduler, e.g. queue
+
+
+ */
+
+
+/*! \page pattern Thread Pool Pattern
+
+
+In the thread pool pattern in programming, a number of N threads are created to perform a number of M tasks, usually organized in a queue. Typically, N << M. As soon as a thread completes its task, it will request the next task from the queue until all tasks have been completed. The thread can then terminate, or sleep until there are new tasks available.
+
+The number of threads used (N) is a parameter that can be tuned to provide the best performance.
+
+The advantage of using a Thread Pool over creating a new thread for each task, is that thread creation and destruction overhead is negated, which may result in better performance and better system stability.
+
+<BR>
+<B>From <A HREF="http://en.wikipedia.org/wiki/Thread_pool_pattern"> Wikipedia </A>, the free encyclopedia.</B>
+
+
+
+ */
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm
new file mode 100644
index 0000000000..006ce09490
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm
@@ -0,0 +1,38 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Design</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="intro.html">TODO5</A> |
+ <A CLASS="qindex" HREF="pattern.html">Thread Pool Pattern</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox
new file mode 100644
index 0000000000..128a4089ad
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/examples
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../include
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = examples.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = examples_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt
new file mode 100644
index 0000000000..fbb29f4d33
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt
@@ -0,0 +1,14 @@
+
+/*! \page intro TODO3
+
+See src/examples/mergesort/mergesort.cpp
+<BR>
+
+ */
+
+
+/*! \page pattern TODO4
+TODO4
+
+ */
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm
new file mode 100644
index 0000000000..d35512cf52
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm
@@ -0,0 +1,38 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Examples</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="intro.html">TODO3</A> |
+ <A CLASS="qindex" HREF="pattern.html">TODO4</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm
new file mode 100644
index 0000000000..1debd97adf
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm
@@ -0,0 +1,17 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm
new file mode 100644
index 0000000000..75ef22b181
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm
@@ -0,0 +1,17 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Overview</A> |
+ <A CLASS="qindex" HREF="reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm
new file mode 100644
index 0000000000..7c177c9f33
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm
@@ -0,0 +1,30 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+
+ <P align="right" valign="top">
+ Hosted by
+ <A HREF="http://sourceforge.net">
+ <IMG src="http://sflogo.sourceforge.net/sflogo.php?group_id=158064&type=2"
+ width="125"
+ height="37"
+ border="0"
+ align="top"
+ alt="SourceForge.net Logo"/>
+ </A>
+ </P>
+
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm
new file mode 100644
index 0000000000..4a6f80c53b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm
@@ -0,0 +1,29 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Overview</A> |
+ <A CLASS="qindex" HREF="reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+
+ <P align="right" valign="top">
+ Hosted by
+ <A HREF="http://sourceforge.net">
+ <IMG src="http://sflogo.sourceforge.net/sflogo.php?group_id=158064&type=2"
+ width="125"
+ height="37"
+ border="0"
+ align="top"
+ alt="SourceForge.net Logo"/>
+ </A>
+ </P>
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html
new file mode 100644
index 0000000000..f36e87310d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html
@@ -0,0 +1,9 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <meta http-equiv="refresh" content="2;url=overview/index.html">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox
new file mode 100644
index 0000000000..3021c3972d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER = 0.2.5
+OUTPUT_DIRECTORY = ../../../doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../../boost/threadpool
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = overview.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH = ../../..
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = overview_header.htm
+HTML_FOOTER = overview_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt
new file mode 100644
index 0000000000..3a995fffb9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt
@@ -0,0 +1,205 @@
+/*! \mainpage threadpool
+
+
+\section intro_sec threadpool
+threadpool is a cross-platform C++ thread pool library. In general terms thread pools
+are an efficient mechanism for asynchronous task processing within the same process.
+They realise the <A HREF="design/pattern.html"> thread pool pattern</A>.
+
+A thread pool manages a group of threads in order to process a large number of tasks.
+Since multiple threads can be executed in parallel this approach may be very efficient regarding the overall program performance on many computer systems. By restricting the number of threads and by reusing them resources are saved
+and additionally the system stability is increased.
+
+The threadpool library provides a convenient way for dispatching asynchronous tasks. Pools can be customized, managed dynamically and easily integrated into your software.
+
+
+\section dev_status_sec Development Status & Future Work
+The threadpool core classes are completed and the implemenation can be considered ready for production code. The library is used by several commercial server applications and can handle high workload without problems. I'm currently working on helper and service classes which make the
+usage of the pool more comfortable. A small tutorial introduces the thread pool and
+more example code will be added in the future. The documentation is far away from being finished.
+<BR>
+<BR><A HREF="http://threadpool.cvs.sourceforge.net/threadpool/threadpool">Browse CVS Repository</A>
+<BR>
+
+<P>
+Features
+- Policy-based thread pool implementation<BR>
+- Scheduling policies: fifo, lifo and priority<BR>
+- Size policies: static_size<BR>
+- Size policy controller: empty_controller, resize_controller<BR>
+- Shutdown policies: wait_for_all_tasks, wait_for_active_tasks, immediately<BR>
+- Smooth integration into STL and boost<BR>
+</P>
+
+<P>
+Future Work
+- More policies: deadline_scheduler, ...<BR>
+- Possibility of limiting the number of pending tasks<BR>
+- Futures (handles to results of scheduled functions)<BR>
+- More examples to illustrate the usage of the library<BR>
+- Provide Unit tests<BR>
+</P>
+
+
+
+
+\section down_sec Download Section
+<P>
+threadpool 0.2.5 (Development Snapshot)
+- <A HREF="http://prdownloads.sourceforge.net/threadpool/threadpool-0_2_5-src.zip?download">threadpool-0_2_5-src.zip</A><BR>
+- <A HREF="http://prdownloads.sourceforge.net/threadpool/threadpool-0_2_5-doc.zip?download">threadpool-0_2_5-doc.zip</A><BR>
+</P>
+
+For more information on the revisions see \ref changelog.
+
+
+\section platforms_sec Supported Platforms
+threadpool is highly portable. It runs on any platform on which Boost threads are available: Linux, Windows, Mac OS 9/X, Solaris, etc.
+
+
+\section boost_sec Boost Libraries
+Boost is a collection of high-quality C++ libraries and works on almost any
+modern operating system, including UNIX and Windows variants.
+In fact threadpool is only a small extension to the portable Boost source libraries.
+It incorporates the thread pool concept by using the thread library from William Kempf.
+For more information on this excellent library visit <A HREF="http://www.boost.org">Boost.org</A>.
+
+
+\section installation_sec Installing & Using threadpool
+threadpool consists only of header files, and so there is no need to build the library itself
+before using it in your own applications. You simply need to add the
+following directories to your compiler include path:<BR>
+ - threadpool's include directory<BR>
+ - the boost directory (e.g. the one called boost_1_37_0)<BR>
+
+Furthermore you have to compile boost's thread library and link against it (libboost_thread-*.lib under Windows).
+
+
+
+\section license_sec Software License
+threadpool is released under the \ref license "Boost Software License".
+This license encourages both commercial and non-commercial use.
+
+
+\section acknowledgments_sec Acknowledgments
+This library was written by Philipp Henkel.
+<P>
+I appreciate your suggestions, and would love to know if you
+use threadpool. Hopefully you will enjoy it and find it useful.
+Please post questions, comments, bugs, or contact me at:
+
+</P>
+
+threadpool@googlemail.com<BR>
+or<BR>
+<A HREF="http://www.sourceforge.net/projects/threadpool">www.sourceforge.net/projects/threadpool</A>
+<BR>
+<BR>
+*/
+
+
+
+/*! \page license Software License
+
+\verbinclude LICENSE_1_0.txt
+
+*/
+
+
+
+ /*! \page changelog Change Log
+
+ <B>0.2.5 (Stable)</B>
+ - Made threadpool compatible to boost::thread 1.37
+ - Fixed hang problem in shutdown method (Thanks to Sohail Somani)
+ - Adapted repository layout to boost (Thanks to Alex Ott)
+
+<B>0.2.4 (Stable)</B>
+ - Made threadpool compatible to boost::thread 1.35.x code base
+ - Fixed compiler warning in scope_guard.hpp
+
+<B>0.2.4 (Stable)</B>
+ - Made threadpool compatible to boost::thread 1.35.x code base
+ - Fixed compiler warning in scope_guard.hpp
+
+<B>0.2.3 (Development)</B>
+ - Implemented workaround for Sun C++ Pro compiler bug in pool_core
+ - Removed subtask implementation (there was no demand for this feature)
+ - Improved shutdown policies
+
+<B>0.2.2 (Development)</B>
+ - Refactored SizePolicy and added SizePolicyController
+ - Moved policies into separate files
+ - Fixed some compiler problems (GCC)
+ - Implemented size_controller handling
+ - Implemented two size policies: static_size and fixed_size
+ - Refactored worker_thread handling, moved policies from pool_core to pool
+ - Specialized schedule function for usage with futures
+ - Added compile test project
+ - Improved constness in pool core class
+ - Fixed timed wait
+ - Implemented futures (in progress)
+ - Added result_type to all functors
+
+<B>0.2.1 (Development)</B>
+ - Pool base class (thread_pool) has now reference semantics.
+ - Large refactorings: Removed scoped_pool, reimplemented worker (now worker_thread)
+ - Fixed odd resize behaviour. Now resize changes the number of threads immediately.
+ - Apply pimpl idiom on pool core class (to make the ugly scoped_pool class needless)
+ - Introduced scheduling policies
+ - Switched to policy-based design (PBD), inspired by Scott Meyers C++ workshop
+ - Cosmetic code change: Replaced keyword 'class' with 'typename' in template definitions
+ - Revised tutorials
+ - New requirements: tasks functions should not and schedulers shall not throw exceptions
+
+<B>0.2.0 (Development)</B>
+ - Moved threadpool into the boost namespace: boost::threadpool
+ - Used keyword volatile to indicate thread-safe member functions
+ - Used volatile on primitve types were appropriate
+ - Moved worker to detail directory
+ - Fixed thread deletion
+ - Extended wait functionality (waiting for idle threads was implemented)
+ - Renamed 'join()' to 'wait()' as 'join' indicates the termination of thread. That was not the case in pool::join.
+ - Changed internal container of lifo and fifo schedulers to improve efficiency.
+ - Improved code reference documentation (source code browser)
+ - Renamed thread_func into task_func
+ - Added += operator to scoped_pool to ease scheduling of tasks
+ - Refactored file structures and class names
+ - Added a new task concept (named subtask) which allows the combination of sequential and parallel execution
+ - Added new task adaptor for looped or timed tasks: looped_task_func
+ - Introduced function clear() which can be used to remove all tasks from the pool and schedulers
+ - New function pool::active() which returns the number of active tasks
+
+<B>0.1.8 (Development)</B>
+ - Fixed some compile errors which were reported by gcc
+ - Wrote tutorial "Prioritized Tasks"
+
+<B>0.1.7 (Development)</B>
+ - Added Visual Studio 2005 project files for tutorial and examples
+
+<B>0.1.6 (Development)</B>
+ - Replaced task adaptor 'task' with boost::bind
+ - Workers are unregistered from thread_group when they are terminated
+ - Working on example boost::iostreams packet_filter
+
+<B>0.1.5 (Development)</B>
+ - Finished threadpool reference
+ - Class pool_adaptor was replaced by smart_pool
+ - Minor pool improvements
+ - First tutorial page online
+
+<B>0.1.4 (Development)</B>
+ - Created the pool's homepage: http://threadpool.sourceforge.net
+ - Improved documentation
+ - Added build scripts
+
+<B>0.1.3 (Development)</B>
+ - First public release
+ - Added mergesort example
+ - Added tutorial
+ - Implementation of threadpool core and related classes
+
+ */
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm
new file mode 100644
index 0000000000..dc6e9f6c18
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm
@@ -0,0 +1,36 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Overview</A> |
+ <A CLASS="qindex" HREF="reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Overview</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Main Page</A> |
+ <A CLASS="qindex" HREF="changelog.html">Change Log</A> |
+ <A CLASS="qindex" HREF="license.html">Software License</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox
new file mode 100644
index 0000000000..d0fb398834
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox
@@ -0,0 +1,220 @@
+# Doxyfile 1.4.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/reference
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../../boost/threadpool
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = YES
+SORT_BY_SCOPE_NAME = YES
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = ../../../boost ../../../boost/threadpool
+FILE_PATTERNS = *.hpp
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH = /../examples
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = reference_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = NO
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = NO
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = NO
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = NO
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm
new file mode 100644
index 0000000000..40fd7423aa
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm
@@ -0,0 +1,40 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Reference</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="annotated.html">Class List</A> |
+ <A CLASS="qindex" HREF="functions.html">Member Functions</A> |
+ <A CLASS="qindex" HREF="namespacemembers.html">Typedefs</A> |
+ <A CLASS="qindex" HREF="files.html">File List</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css
new file mode 100644
index 0000000000..8593700905
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css
@@ -0,0 +1,331 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+ font-size: 90%;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
+}
+CAPTION { font-weight: bold }
+DIV.sidebar {
+ width: 210px;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-bottom: 20px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.sidebar TABLE TR TD {
+ font-size: 80%;
+}
+DIV.sidebar UL {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+DIV.qindex {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.nav {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddff;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff;
+}
+A.anchor {
+ text-decoration: none;
+ color: #000000;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { text-decoration: none; font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+.fragment {
+ font-family: Fixed, monospace;
+ font-size: 95%;
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+TD.md { background-color: #F4F4FB; font-weight: bold; }
+TD.mdPrefix {
+ background-color: #F4F4FB;
+ color: #606060;
+ font-size: 80%;
+}
+TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
+TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #e8eef2;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #e8eef2;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+.mdTable {
+ border: 1px solid #868686;
+ background-color: #F4F4FB;
+}
+.mdRow {
+ padding: 8px 10px;
+}
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.search { color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+TD.tiny { font-size: 75%;
+}
+a {
+ color: #1A41A8;
+}
+a:visited {
+ color: #2A3798;
+}
+.dirtab { padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+TH.dirtab { background: #e8eef2;
+ font-weight: bold;
+}
+HR { height: 1px;
+ border: none;
+ border-top: 1px solid black;
+}
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox
new file mode 100644
index 0000000000..66a39edf23
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/tutorial
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../include/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = tutorial.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = tutorial_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt
new file mode 100644
index 0000000000..e89c96d9af
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt
@@ -0,0 +1,207 @@
+/*! \page intro Quick Start
+
+This tutorial introduces the threadpool library by discussing an easy to understand source listing:
+
+\code
+01
+02 #include "threadpool.hpp"
+03
+04 using namespace boost::threadpool;
+05
+06 // Some example tasks
+07 void first_task()
+08 {
+09 ...
+10 }
+11
+13 void second_task()
+14 {
+15 ...
+16 }
+17
+19 void third_task()
+20 {
+21 ...
+22 }
+23
+24 void execute_with_threadpool()
+25 {
+26 // Create a thread pool.
+27 pool tp(2);
+28
+29 // Add some tasks to the pool.
+30 tp.schedule(&first_task);
+31 tp.schedule(&second_task);
+32 tp.schedule(&third_task);
+33
+34 // Leave this function and wait until all tasks are finished.
+35 }
+36
+\endcode
+
+We start by including the necessary header files. The complete threadpool functionality can be used by simply including
+the "threadpool.hpp" header file at line 2.
+
+The three functions first_task(), second_task and third_task() are placeholders
+for tasks that should be executed by our pool.
+
+The thread pool is created at line 27. The argument indicates the number of initial threads.
+The new pool contains two threads that is two tasks can be processed in parallel. The pool's threads
+are sleeping until tasks are added.
+By default it uses a Fifo scheduling strategy.
+Fifo is an abbreviation of "first in, first out"
+and means in this case that the first task which is added is the
+first that will be executed. Generally this is the expected default behaviour
+since the tasks are executed in the order they are added to the pool.
+
+In line 30 to 32 the task functions are scheduled asynchronously using the pool's schedule function.
+A task is registered and it will be executed as soon as one of the pool's threads is idle.
+It is very important to understand that the task is only scheduled for execution.
+Schedule returns immediately and there are no guarantees about when the tasks are executed and how long
+the processing will take. As they are added to a fifo pool with two threads the following is true:
+- the execution of first_task begins first
+- second_task is started after first_task
+- third_task is begun at last
+- a maximum of two tasks may are processed in parallel
+- each scheduled task will be executed once only
+
+
+The pool reference tp is created in the scope of the function execute_with_threadpool(). When this
+function returns at line 35 tp goes out of scope and the pool will be destructed. As the default ShutdownPolicy
+is wait_for_all_tasks it is ensured that all tasks are processed before the pool is destroyed.
+
+\code
+101
+102 ...
+103 execute_with_threadpool(); // execute first_task, second_task and third_task
+104 // When this line is reached all tasks are finished and the pool is destructed.
+105
+\endcode
+
+The small code example clarifies the issue. When the function leaves the pool is shut down
+and waits for the tasks. That means the current thread of execution is blocked
+at the end of the execute_with_threadpool as long as
+the processing of tasks is in progress.
+
+<BR>
+*/
+
+
+/*! \page prioritized Prioritized Tasks
+
+TODO This tutorial is out dated.
+
+It's easy to prioritize asynchronous tasks by using the task adaptor prio_task_func.
+The following source listing illustrates how to setup the pool and add the tasks:
+
+\code
+01
+02 #include "threadpool.hpp"
+03
+04 using namespace boost::threadpool;
+05
+06 // Some example tasks
+07 void normal_task()
+08 {
+09 ...
+10 }
+11
+13 void important_task()
+14 {
+15 ...
+16 }
+17
+18 void execute_prioritized()
+19 {
+20 // Create prioritized thread pool container without any threads.
+21 scoped_pool<prio_pool, 0> tp;
+22
+23 // Add some tasks to the pool.
+24 tp += prio_task_func(5, &normal_task);
+25 tp += prio_task_func(100, &important_task);
+26 tp += prio_task_func(7, &normal_task);
+27
+28 // Add the some threads to the pool. This will start the execution of the tasks.
+29 tp->resize(2);
+30
+31 // The tasks are processed according to their priority: important_task(100), nonrelevant_task(7), nonrelevant_task(5).
+32
+33 tp->wait();
+34
+35 // Now all tasks are finished and the pool will be destroyed safely when tp goes out of scope.
+36 }
+37
+\endcode
+
+Like in the first tutorial we start including the main header file and defining some tasks.
+
+At line 21 a prioritized thread pool is created. That means that the pool's tasks are arranged
+according to their priority before they get executed. Therefore the tasks themselves have to realize a partial ordering based
+on operator<.
+
+The adaptor prio_thread_func satisfies our requirements regarding the order and is just a small wrapper object for
+the task functions. In line 24 to 26 some prioritized tasks are scheduled. This time the pool's schedule function is used and like smart pool's += operator
+this function returns immediately.
+
+At line 29 the first thread is added to the pool and the execution of important_task begins. As we have only one thread
+the tasks are processed sequentially.
+
+Finally wait() is called to ensure that all tasks are finished before our example function returns
+and the pool is destroyed. This is very important since the behavior is undefined if pool's lifetime ends while tasks are executed.
+
+*/
+
+
+/*! \page task_adaptor Arbitrary Task Functions
+
+TODO This tutorial is out dated.
+
+
+\section member_task Member Task Functions
+
+using namespace boost::threadpool;
+
+TODO <BR>
+boost::bind(member_function, shared_ptr)
+26 tp->schedule(boost::bind(task_with_parameter, 42));
+12 // Second example task
+13 void task_with_parameter(int value)
+14 {
+15 ...
+16 }
+
+\section member_task Functions With Arguments
+
+*/
+
+
+/*! \page instantiation Advanced Instantiation
+
+TODO This tutorial is out dated.
+
+TODO <BR>
+Pool instantiation
+\code
+
+ boost::shared_ptr<fifo_pool> tp = fifo_pool::create_pool(5);
+
+ print(" Add tasks ...\n");
+ tp->schedule(&task_1);
+ tp->schedule(&task_2);
+ tp->schedule(&task_3);
+
+ tp->schedule(looped_task_func(&looped_task, 1500));
+
+ print(" Wait until all tasks are finished ...\n");
+ tp->wait();
+ print(" Tasks finished!\n");
+
+\endcode
+
+
+\code
+ typedef threadpool::pool<boost::function0<void>, threadpool::fifo_scheduler<boost::function0<void> > > pool_type;
+ boost::shared_ptr< pool_type > tp = pool_type::create_pool(5);
+\endcode
+
+*/ \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm
new file mode 100644
index 0000000000..b087ec0f9f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm
@@ -0,0 +1,40 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Tutorial</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="intro.html">Quick Start</A> |
+ <A CLASS="qindex" HREF="prioritized.html">Prioritized Tasks</A> |
+ <A CLASS="qindex" HREF="task_adaptor.html">Arbitrary Task Functions</A> |
+ <A CLASS="qindex" HREF="instantiation.html">Advanced Pool Instantiation</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v2
new file mode 100644
index 0000000000..8ff7fe2dbb
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe mergesort : mergesort.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp
new file mode 100644
index 0000000000..338153453b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp
@@ -0,0 +1,200 @@
+/*! \file
+ * \brief Mergesort example.
+ *
+ * This example shows how to use the threadpool library.
+ *
+ * Copyright (c) 2005-2006 Philipp Henkel
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * http://threadpool.sourceforge.net
+ *
+ */
+
+
+#include <boost/threadpool.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/smart_ptr.hpp>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+
+
+
+using namespace std;
+using namespace boost::threadpool;
+
+//
+// Helpers
+boost::mutex m_io_monitor;
+
+void print(string text)
+{
+ boost::mutex::scoped_lock lock(m_io_monitor);
+ cout << text;
+}
+
+template<class T>
+string to_string(const T& value)
+{
+ ostringstream ost;
+ ost << value;
+ ost.flush();
+ return ost.str();
+}
+
+unsigned long get_ms_diff(boost::xtime& start, boost::xtime& end)
+{
+ boost::xtime::xtime_sec_t start_ms = start.sec * 1000 + start.nsec/1000000;
+ boost::xtime::xtime_sec_t end_ms = end.sec * 1000 + end.nsec/1000000;
+ return static_cast<unsigned long>(end_ms - start_ms);
+}
+
+class image
+{
+public:
+ image() : m_content(0) {}
+ image(int content) : m_content(content) {}
+
+ image(const image& src)
+ {
+ m_content = src.m_content;
+ }
+
+ bool operator<(const image& l) const
+ {
+ { // simulate time needed for image comparision
+ boost::xtime xt;
+ boost::xtime_get(&xt, boost::TIME_UTC);
+ int duration = 1+(m_content % 4);
+ xt.nsec += 250 * 1000 * duration;
+ boost::thread::sleep(xt);
+ print(".");
+ }
+ return m_content < l.m_content;
+ }
+
+protected:
+ int m_content; // represents image data in this example
+};
+
+
+template<class T>
+class merge_job
+{
+public:
+ merge_job(boost::shared_array<T> data, unsigned int position, unsigned int length)
+ : m_data(data)
+ , m_position(position)
+ , m_length(length)
+ {
+ print("merge job created : " + to_string(m_position) +", "+ to_string(m_length) +"\n");
+ }
+
+ void run()
+ {
+ print("merge job running : " + to_string(m_position) +", "+ to_string(m_length) +"\n");
+
+ T* begin = m_data.get();
+ std::advance(begin, m_position);
+
+ T* mid = m_data.get();
+ std::advance(mid, m_position + m_length/2);
+
+ T* end = m_data.get();
+ std::advance(end, m_position + m_length);
+
+ std::inplace_merge(begin, mid, end);
+
+ print("\nmerge job finished: " + to_string(m_position) +", "+ to_string(m_length) +"\n");
+ }
+
+protected:
+ boost::shared_array<T> m_data;
+ unsigned int m_position;
+ unsigned int m_length;
+};
+
+
+
+
+//
+// A demonstration of the thread_pool class
+int main (int argc, char * const argv[])
+{
+ print("MAIN: construct thread pool\n");
+
+
+
+ boost::xtime start;
+ boost::xtime_get(&start, boost::TIME_UTC);
+
+ int exponent = 7;
+ int data_len = 1 << exponent; // = pow(2, exponent)
+
+ print("MAIN: sort array with "+ to_string(data_len) + " elements.\n");
+
+ boost::shared_array<image> data(new image[data_len]);
+
+ // fill array with arbitrary values (not sorted ascendingly)
+ for(int i = 0; i < data_len; i++)
+ {
+ data[i] = image((data_len - i - 1) % 23);
+ }
+
+
+ /***************************/
+ /* Standard implementation */
+ /***************************/
+
+ pool tp;
+ tp.size_controller().resize(5);
+
+// merge data array
+ for(int step = 1; step <= exponent; step++)
+ {
+ print("\nMAIN: merge step "+ to_string(step)+"\n");
+
+ // divide array into partitions
+ int partition_size = 1 << step;
+ for(int partition = 0; partition < data_len/partition_size; partition++)
+ {
+ // sort partition
+ boost::shared_ptr<merge_job<image> > job(new merge_job<image>(data, partition*partition_size, partition_size));
+ //tp->schedule(prio_task_func(5, boost::bind(&merge_job<image>::run, job)));
+ schedule(tp, boost::bind(&merge_job<image>::run, job));
+ // schedule(tp, job);
+ }
+ tp.wait(); // wait until all partitions are sorted
+ }
+
+ boost::xtime end;
+ boost::xtime_get(&end, boost::TIME_UTC);
+
+ print("\nMAIN: duration " + to_string(get_ms_diff(start, end)) + " ms \n");
+
+ print("\nMAIN: check if array is sorted... \n");
+
+ // check if array is sorted ascendingly
+ bool ascending = true;
+ for(int i = 0; i < data_len-1; i++)
+ {
+ if(data[i+1] < data[i])
+ {
+ ascending = false;
+ }
+ }
+
+ if(ascending)
+ {
+ print("\nMAIN: array is sorted\n");
+ }
+ else
+ {
+ print("\nMAIN: array is NOT sorted!\n");
+ }
+
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v2
new file mode 100644
index 0000000000..85b2bcb0fd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe quickstart : quickstart.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README
new file mode 100644
index 0000000000..4f97ce51d7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README
@@ -0,0 +1,7 @@
+Supposing the boost directory is in /usr/local/lib, it is also worth to mention that they need to
+set LD_LIBRARY_PATH as follows:
+export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):/usr/local/lib
+
+Please adapt threadpool.makefile to your system.
+
+Special thanks to Rudy Prabowo who contributed this example to help linux users.
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp
new file mode 100644
index 0000000000..858573a0a8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp
@@ -0,0 +1,50 @@
+/*! \file
+ * \brief Quick start example.
+ *
+ * This is a very simple example which can be used to configure the threadpool environment on your system.
+ *
+ * Copyright (c) 2005-2006 Philipp Henkel
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * http://threadpool.sourceforge.net
+ *
+ */
+
+#include <iostream>
+
+#include <boost/threadpool.hpp>
+
+using namespace std;
+using namespace boost::threadpool;
+
+// Some example tasks
+void first_task()
+{
+ cout << "first task is running\n" ;
+}
+
+void second_task()
+{
+ cout << "second task is running\n" ;
+}
+
+int main(int argc,char *argv[])
+{
+ // Create fifo thread pool container with two threads.
+ pool tp(2);
+
+ // Add some tasks to the pool.
+ tp.schedule(&first_task);
+ tp.schedule(&second_task);
+
+ // Wait until all tasks are finished.
+ tp.wait();
+
+ // Now all tasks are finished!
+ return(0);
+}
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v2
new file mode 100644
index 0000000000..e14c124a8d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe compile_all : compile_all.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp
new file mode 100644
index 0000000000..1c349d4406
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp
@@ -0,0 +1,149 @@
+/*! \file
+* \brief threadpool tutorial.
+*
+* This file contains a tutorial for the threadpool library.
+*
+* Copyright (c) 2005-2006 Philipp Henkel
+*
+* Distributed under the Boost Software License, Version 1.0. (See
+* accompanying file LICENSE_1_0.txt or copy at
+* http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+
+
+#include <iostream>
+#include <sstream>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+
+#include <boost/threadpool.hpp>
+
+using namespace std;
+using namespace boost::threadpool;
+
+
+//
+// Helpers
+boost::mutex m_io_monitor;
+
+void print(string text)
+{
+ boost::mutex::scoped_lock lock(m_io_monitor);
+ cout << text;
+}
+
+template<typename T>
+string to_string(T const & value)
+{
+ ostringstream ost;
+ ost << value;
+ ost.flush();
+ return ost.str();
+}
+
+
+
+//
+// An example task functions
+void task_1()
+{
+ print(" task_1()\n");
+}
+
+void task_2()
+{
+ print(" task_2()\n");
+}
+
+void task_3()
+{
+ print(" task_3()\n");
+}
+
+int task_4()
+{
+ print(" task_4()\n");
+ return 4;
+}
+
+void task_with_parameter(int value)
+{
+ print(" task_with_parameter(" + to_string(value) + ")\n");
+}
+
+int loops = 0;
+bool looped_task()
+{
+ print(" looped_task()\n");
+ return ++loops < 5;
+}
+
+
+int task_int()
+{
+ print(" task_int()\n");
+ return 23;
+}
+
+
+void fifo_pool_test()
+{
+ pool tp;
+
+ tp.schedule(&task_1);
+ tp.schedule(boost::bind(task_with_parameter, 4));
+
+ if(!tp.empty())
+ {
+ tp.clear(); // remove all tasks -> no output in this test
+ }
+
+ size_t active_threads = tp.active();
+ size_t pending_threads = tp.pending();
+ size_t total_threads = tp.size();
+
+ size_t dummy = active_threads + pending_threads + total_threads;
+ dummy++;
+
+ tp.size_controller().resize(5);
+ tp.wait();
+}
+
+void lifo_pool_test()
+{
+ lifo_pool tp;
+ tp.size_controller().resize(0);
+ schedule(tp, &task_1);
+ tp.size_controller().resize(10);
+ tp.wait();
+}
+
+void prio_pool_test()
+{
+ prio_pool tp(2);
+ schedule(tp, prio_task_func(1, &task_1));
+ schedule(tp, prio_task_func(10,&task_2));
+}
+
+
+void future_test()
+{
+ fifo_pool tp(5);
+ future<int> fut = schedule(tp, &task_4);
+ int res = fut();
+}
+
+
+int main (int , char * const [])
+{
+ fifo_pool_test();
+ lifo_pool_test();
+ prio_pool_test();
+ future_test();
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v2
new file mode 100644
index 0000000000..5b9d02b459
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe tutorial : tutorial.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp
new file mode 100644
index 0000000000..4cc688509e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp
@@ -0,0 +1,263 @@
+/*! \file
+* \brief threadpool tutorial.
+*
+* This file contains a tutorial for the threadpool library.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Distributed under the Boost Software License, Version 1.0. (See
+* accompanying file LICENSE_1_0.txt or copy at
+* http://www.boost.org/LICENSE_1_0.txt)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+//#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+
+#include <iostream>
+#include <sstream>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+#include <boost/threadpool.hpp>
+
+using namespace std;
+using namespace boost::threadpool;
+
+//
+// Helpers
+boost::mutex m_io_monitor;
+
+void print(string text)
+{
+ boost::mutex::scoped_lock lock(m_io_monitor);
+ cout << text;
+}
+
+template<typename T>
+string to_string(T const & value)
+{
+ ostringstream ost;
+ ost << value;
+ ost.flush();
+ return ost.str();
+}
+
+
+
+//
+// An example task functions
+void task_1()
+{
+ print(" task_1()\n");
+ throw 5;
+}
+
+void task_2()
+{
+ print(" task_2()\n");
+ throw 5;
+}
+
+void task_3()
+{
+ print(" task_3()\n");
+}
+
+void task_with_parameter(int value)
+{
+ print(" task_with_parameter(" + to_string(value) + ")\n");
+}
+
+int loops = 0;
+bool looped_task()
+{
+ print(" looped_task()\n");
+ return ++loops < 5;
+}
+
+
+int task_int_23()
+{
+ print(" task_int_23()\n");
+ return 23;
+}
+
+int task_int_1()
+{
+ print(" task_int_1()\n");
+ return 1;
+}
+
+
+class CTest
+{
+ pool m_pool;
+public:
+ CTest()
+ : m_pool(pool(1000))
+ {
+ }
+};
+
+
+//
+// A demonstration of the thread_pool class
+int main (int , char * const [])
+{
+ print("\nWelcome to the threadpool tutorial!\n");
+
+ print("\n**************************************\n");
+ print("Section 1: Quick Start\n");
+
+ //void func()
+ {
+ print(" Create a new thread pool\n");
+ pool tp(2); // tp is handle to the pool
+
+ // Add tasks
+ tp.schedule(&task_1);
+ tp.schedule(&task_2);
+ tp.schedule(&task_3);
+ tp.schedule(boost::bind(task_with_parameter, 4));
+
+ // The pool handle tp is allocated on stack and will
+ // be destructed if it gets out of scope. Before the
+ // pool is destroyed it waits for its tasks.
+ // That means the current thread of execution is
+ // blocked at the end of the function
+ // (until all tasks are processed).
+ // while (&tp){int i = 3; ++i;}
+ }
+
+ { // Section Futures
+ print("\n**************************************\n");
+ print("Section 1: Futures\n");
+
+ //typedef thread_pool<task_func, fifo_scheduler, static_size, empty_controller, wait_for_all_tasks> test_pool;
+
+ pool tp;
+
+// tp.resize(0);
+ tp.pending();
+// tp.clear();
+ boost::xtime t;
+ tp.wait(t);
+ bool test = tp.empty();
+ if(test)
+ {
+ test = false;
+ }
+
+ tp.size_controller().resize(2);
+
+ //test_pool::size_controller_type controller = tp.size_controller();
+// controller.resize(5);
+
+ schedule(tp, &task_int_1);
+ future<int> res = schedule(tp, &task_int_23);
+ future<int> res2 = schedule(tp, &task_int_1);
+
+ res.wait();
+ int value = res.get() + res2.get();
+
+ res.cancel();
+ res.is_cancelled();
+value ++;
+
+//thread_pool<boost::function0<int>, fifo_scheduler> test2332;
+
+//TODO runnable comile test
+ }
+
+
+
+ { // Section 2
+ print("\n**************************************\n");
+ print("Section 2: Controlling scheduling\n");
+
+ // Create a lifo_pool: last task in, first task out
+ lifo_pool tp(0);
+
+ print(" Add tasks (using the pool's schedule function)\n");
+ schedule(tp, &task_1);
+ schedule(tp, &task_2);
+ schedule(tp, &task_3);
+
+ // tp.wait(); This would be a deadlock as there are no threads which process the tasks.
+
+ print(" Add some threads ...\n");
+ tp.size_controller().resize(5);
+
+ print(" Wait until all tasks are finished ...\n");
+ tp.wait();
+ print(" Tasks finished!\n");
+ }
+
+
+
+ { // Section 3:
+ print("\n**************************************\n");
+ print("Section 3: Prioritized Tasks\n");
+
+ prio_pool tp(0);
+
+
+ print(" Add prioritized tasks ...\n");
+ schedule(tp, prio_task_func(1, &task_1));
+ schedule(tp, prio_task_func(10,&task_2));
+ schedule(tp, prio_task_func(5,&task_3));
+
+ // Tasks are ordered according to their priority: task_2, task_4, task_3, task_1
+
+ print(" Thread added\n");
+ tp.size_controller().resize(10);
+
+ print(" Wait until all tasks are finished ...\n");
+ tp.wait();
+ print(" Tasks finished!\n");
+ }
+
+
+/* */
+ { // Section 5:
+ print("\n**************************************\n");
+ print("Section 5: Advanced thread pool instantiation\n");
+ // Create the pool directly
+/*
+TODO
+boost::shared_ptr<fifo_pool> tp = fifo_pool::create_pool(5);
+
+ print(" Add tasks ...\n");
+ tp->schedule(&task_1);
+ tp->schedule(&task_2);
+ tp->schedule(&task_3);
+ tp->schedule(looped_task_func(&looped_task, 1500));
+
+ print(" Wait until all tasks are finished ...\n");
+ tp->wait();
+*/
+
+ print(" Tasks finished!\n");
+
+ }
+
+
+ print("\n**************************************\n");
+ print("Tutorial finished!\n");
+
+
+
+ { // Section Compile Tests
+ print("\n**************************************\n");
+ print("Section Compile Tests\n");
+
+
+ fifo_pool tp;
+ tp.size_controller().resize(0);
+ tp.empty();
+ }
+
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam b/graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam
new file mode 100644
index 0000000000..e94f7232e0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam
@@ -0,0 +1,2 @@
+import os ;
+path-constant BOOST_ROOT : [ os.environ BOOST_ROOT ] ;
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt b/graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt
new file mode 100644
index 0000000000..f1a2e1f1e9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required (VERSION 3.0.2)
+project (utf8cpp VERSION 3.2 LANGUAGES CXX)
+
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(IS_ROOT_PROJECT ON)
+else()
+ set(IS_ROOT_PROJECT OFF)
+endif()
+
+option(UTF8_TESTS "Enable tests for UTF8-CPP" ${IS_ROOT_PROJECT})
+option(UTF8_INSTALL "Enable installation for UTF8-CPP" ${IS_ROOT_PROJECT})
+option(UTF8_SAMPLES "Enable building samples for UTF8-CPP" ${IS_ROOT_PROJECT})
+
+add_library(utf8cpp INTERFACE)
+target_include_directories(utf8cpp INTERFACE
+ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/source>"
+ $<INSTALL_INTERFACE:include/utf8cpp>
+)
+add_library(utf8::cpp ALIAS utf8cpp)
+
+if(UTF8_INSTALL)
+ if(MSVC)
+ set(DEF_INSTALL_CMAKE_DIR CMake)
+ else()
+ include(GNUInstallDirs) # define CMAKE_INSTALL_*
+ set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/utf8cpp)
+ endif()
+
+ install(DIRECTORY source/ DESTINATION include/utf8cpp)
+ install(TARGETS utf8cpp EXPORT utf8cppConfig)
+ install(EXPORT utf8cppConfig DESTINATION ${DEF_INSTALL_CMAKE_DIR})
+endif()
+
+if(UTF8_SAMPLES)
+ add_executable(docsample ${PROJECT_SOURCE_DIR}/samples/docsample.cpp)
+ target_link_libraries(docsample PRIVATE utf8::cpp)
+endif()
+
+if(UTF8_TESTS)
+ enable_testing()
+ add_subdirectory(tests)
+endif()
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE b/graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/README.md b/graphics/asymptote/LspCpp/third_party/utfcpp/README.md
new file mode 100644
index 0000000000..a519cdb963
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/README.md
@@ -0,0 +1,1503 @@
+# UTF8-CPP: UTF-8 with C++ in a Portable Way
+
+
+## Introduction
+
+C++ developers miss an easy and portable way of handling Unicode encoded strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic. C++11 provides some support for Unicode on core language and library level: u8, u, and U character and string literals, char16_t and char32_t character types, u16string and u32string library classes, and codecvt support for conversions between Unicode encoding forms. In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply roll out their own solutions.
+
+In order to easily handle UTF-8 encoded Unicode strings, I came up with a small, C++98 compatible generic library. For anybody used to work with STL algorithms and iterators, it should be easy and natural to use. The code is freely available for any purpose - check out the [license](./LICENSE). The library has been used a lot in the past ten years both in commercial and open-source projects and is considered feature-complete now. If you run into bugs or performance issues, please let me know and I'll do my best to address them.
+
+The purpose of this article is not to offer an introduction to Unicode in general, and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out [Unicode Home Page](http://www.unicode.org/) or some other source of information for Unicode. Also, it is not my aim to advocate the use of UTF-8 encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from C++, I am sure you have good reasons for it.
+
+## Examples of use
+
+### Introductionary Sample
+
+To illustrate the use of the library, let's start with a small but complete program that opens a file containing UTF-8 encoded text, reads it line by line, checks each line for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
+
+```cpp
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include "utf8.h"
+using namespace std;
+int main(int argc, char** argv)
+{
+ if (argc != 2) {
+ cout << "\nUsage: docsample filename\n";
+ return 0;
+ }
+ const char* test_file_path = argv[1];
+ // Open the test file (must be UTF-8 encoded)
+ ifstream fs8(test_file_path);
+ if (!fs8.is_open()) {
+ cout << "Could not open " << test_file_path << endl;
+ return 0;
+ }
+
+ unsigned line_count = 1;
+ string line;
+ // Play with all the lines in the file
+ while (getline(fs8, line)) {
+ // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
+#if __cplusplus >= 201103L // C++ 11 or later
+ auto end_it = utf8::find_invalid(line.begin(), line.end());
+#else
+ string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+#endif // C++ 11
+ if (end_it != line.end()) {
+ cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
+ cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
+ }
+ // Get the line length (at least for the valid part)
+ int length = utf8::distance(line.begin(), end_it);
+ cout << "Length of line " << line_count << " is " << length << "\n";
+
+ // Convert it to utf-16
+#if __cplusplus >= 201103L // C++ 11 or later
+ u16string utf16line = utf8::utf8to16(line);
+#else
+ vector<unsigned short> utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+#endif // C++ 11
+ // And back to utf-8;
+#if __cplusplus >= 201103L // C++ 11 or later
+ string utf8line = utf8::utf16to8(utf16line);
+#else
+ string utf8line;
+ utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+#endif // C++ 11
+ // Confirm that the conversion went OK:
+ if (utf8line != string(line.begin(), end_it))
+ cout << "Error in UTF-16 conversion at line: " << line_count << "\n";
+
+ line_count++;
+ }
+
+ return 0;
+}
+```
+
+In the previous code sample, for each line we performed a detection of invalid UTF-8 sequences with `find_invalid`; the number of characters (more precisely - the number of Unicode code points, including the end of line and even BOM if there is one) in each line was determined with a use of `utf8::distance`; finally, we have converted each line to UTF-16 encoding with `utf8to16` and back to UTF-8 with `utf16to8`.
+
+Note a different pattern of usage for old compilers. For instance, this is how we convert
+a UTF-8 encoded string to a UTF-16 encoded one with a pre - C++11 compiler:
+```cpp
+ vector<unsigned short> utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+```
+
+With a more modern compiler, the same operation would look like:
+```cpp
+ u16string utf16line = utf8::utf8to16(line);
+```
+If `__cplusplus` macro points to a C++ 11 or later, the library exposes API that takes into
+account C++ standard Unicode strings and move semantics. With an older compiler, it is still
+possible to use the same functionality, just in a little less convenient way
+
+In case you do not trust the `__cplusplus` macro or, for instance, do not want to include
+the C++ 11 helper functions even with a modern compiler, define `UTF_CPP_CPLUSPLUS` macro
+before including `utf8.h` and assign it a value for the standard you want to use - the values are the same as for the `__cplusplus` macro. This can be also useful with compilers that are conservative in setting the `__cplusplus` macro even if they have a good support for a recent standard edition - Microsoft's Visual C++ is one example.
+
+### Checking if a file contains valid UTF-8 text
+
+Here is a function that checks whether the content of a file is valid UTF-8 encoded text without reading the content into the memory:
+
+```cpp
+bool valid_utf8_file(const char* file_name)
+{
+ ifstream ifs(file_name);
+ if (!ifs)
+ return false; // even better, throw here
+
+ istreambuf_iterator<char> it(ifs.rdbuf());
+ istreambuf_iterator<char> eos;
+
+ return utf8::is_valid(it, eos);
+}
+```
+
+Because the function `utf8::is_valid()` works with input iterators, we were able to pass an `istreambuf_iterator` to `it` and read the content of the file directly without loading it to the memory first.
+
+Note that other functions that take input iterator arguments can be used in a similar way. For instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just do something like:
+
+```cpp
+ utf8::utf8to16(it, eos, back_inserter(u16string));
+```
+
+### Ensure that a string contains valid UTF-8 text
+
+If we have some text that "probably" contains UTF-8 encoded text and we want to replace any invalid UTF-8 sequence with a replacement character, something like the following function may be used:
+
+```cpp
+void fix_utf8_string(std::string& str)
+{
+ std::string temp;
+ utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
+ str = temp;
+}
+```
+
+The function will replace any invalid UTF-8 sequence with a Unicode replacement character. There is an overloaded function that enables the caller to supply their own replacement character.
+
+
+## Points of interest
+
+#### Design goals and decisions
+
+The library was designed to be:
+
+1. Generic: for better or worse, there are many C++ string classes out there, and the library should work with as many of them as possible.
+2. Portable: the library should be portable both accross different platforms and compilers. The only non-portable code is a small section that declares unsigned integers of different sizes: three typedefs. They can be changed by the users of the library if they don't match their platform. The default setting should work for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives. Support for post C++03 language features is included for modern compilers at API level only, so the library should work even with pretty old compilers.
+3. Lightweight: follow the "pay only for what you use" guideline.
+4. Unintrusive: avoid forcing any particular design or even programming style on the user. This is a library, not a framework.
+
+#### Alternatives
+
+In case you want to look into other means of working with UTF-8 strings from C++, here is the list of solutions I am aware of:
+
+1. [ICU Library](http://icu.sourceforge.net/). It is very powerful, complete, feature-rich, mature, and widely used. Also big, intrusive, non-generic, and doesn't play well with the Standard Library. I definitelly recommend looking at ICU even if you don't plan to use it.
+2. C++11 language and library features. Still far from complete, and not easy to use.
+3. [Glib::ustring](http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html). A class specifically made to work with UTF-8 strings, and also feel like `std::string`. If you prefer to have yet another string class in your code, it may be worth a look. Be aware of the licensing issues, though.
+4. Platform dependent solutions: Windows and POSIX have functions to convert strings from one encoding to another. That is only a subset of what my library offers, but if that is all you need it may be good enough.
+
+
+## Reference
+
+### Functions From utf8 Namespace
+
+#### utf8::append
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence to a UTF-8 string.
+
+```cpp
+void append(char32_t cp, std::string& s);
+```
+
+`cp`: a code point to append to the string.
+`s`: a utf-8 encoded string to append the code point to.
+
+Example of use:
+
+```cpp
+std::string u;
+append(0x0448, u);
+assert (u[0] == char(0xd1) && u[1] == char(0x88) && u.length() == 2);
+```
+
+In case of an invalid code point, a `utf8::invalid_code_point` exception is thrown.
+
+
+#### utf8::append
+
+Available in version 1.0 and later.
+
+Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence to a UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+```
+
+`octet_iterator`: an output iterator.
+`cp`: a 32 bit integer representing a code point to append to the sequence.
+`result`: an output iterator to the place in the sequence where to append the code point.
+Return value: an iterator pointing to the place after the newly appended sequence.
+
+Example of use:
+
+```cpp
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+```
+
+Note that `append` does not allocate any memory - it is the burden of the caller to make sure there is enough memory allocated for the operation. To make things more interesting, `append` can add anywhere between 1 and 4 octets to the sequence. In practice, you would most often want to use `std::back_inserter` to ensure that the necessary memory is allocated.
+
+In case of an invalid code point, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::next
+
+Available in version 1.0 and later.
+
+Given the iterator to the beginning of the UTF-8 sequence, it returns the code point and moves the iterator to the next position.
+
+```cpp
+template <typename octet_iterator>
+uint32_t next(octet_iterator& it, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the beginning of the next code point.
+`end`: end of the UTF-8 sequence to be processed. If `it` gets equal to `end` during the extraction of a code point, an `utf8::not_enough_room` exception is thrown.
+Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+```
+
+This function is typically used to iterate through a UTF-8 encoded string.
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::peek_next
+
+Available in version 2.1 and later.
+
+Given the iterator to the beginning of the UTF-8 sequence, it returns the code point for the following sequence without changing the value of the iterator.
+
+```cpp
+template <typename octet_iterator>
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+```
+
+
+`octet_iterator`: an input iterator.
+`it`: an iterator pointing to the beginning of an UTF-8 encoded code point.
+`end`: end of the UTF-8 sequence to be processed. If `it` gets equal to `end` during the extraction of a code point, an `utf8::not_enough_room` exception is thrown.
+Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = peek_next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::prior
+
+Available in version 1.02 and later.
+
+Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it decreases the iterator until it hits the beginning of the previous UTF-8 encoded code point and returns the 32 bits representation of the code point.
+
+```cpp
+template <typename octet_iterator>
+uint32_t prior(octet_iterator& it, octet_iterator start);
+```
+
+`octet_iterator`: a bidirectional iterator.
+`it`: a reference pointing to an octet within a UTF-8 encoded string. After the function returns, it is decremented to point to the beginning of the previous code point.
+`start`: an iterator to the beginning of the sequence where the search for the beginning of a code point is performed. It is a safety measure to prevent passing the beginning of the string in the search for a UTF-8 lead octet.
+ Return value: the 32 bit representation of the previous code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars + 3;
+int cp = prior (w, twochars);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+This function has two purposes: one is two iterate backwards through a UTF-8 encoded string. Note that it is usually a better idea to iterate forward instead, since `utf8::next` is faster. The second purpose is to find a beginning of a UTF-8 sequence if we have a random position within a string. Note that in that case `utf8::prior` may not detect an invalid UTF-8 sequence in some scenarios: for instance if there are superfluous trail octets, it will just skip them.
+
+`it` will typically point to the beginning of a code point, and `start` will point to the beginning of the string to ensure we don't go backwards too far. `it` is decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence beginning with that octet is decoded to a 32 bit representation and returned.
+
+In case `start` is reached before a UTF-8 lead octet is hit, or if an invalid UTF-8 sequence is started by the lead octet, an `invalid_utf8` exception is thrown.
+
+In case `start` equals `it`, a `not_enough_room` exception is thrown.
+
+#### utf8::advance
+Available in version 1.0 and later.
+
+Advances an iterator by the specified number of code points within an UTF-8 sequence.
+
+```cpp
+template <typename octet_iterator, typename distance_type>
+void advance (octet_iterator& it, distance_type n, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`distance_type`: an integral type convertible to `octet_iterator`'s difference type.
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the nth following code point.
+`n`: number of code points `it` should be advanced. A negative value means decrement.
+`end`: limit of the UTF-8 sequence to be processed. If `n` is positive and `it` gets equal to `end` during the extraction of a code point, an `utf8::not_enough_room` exception is thrown. If `n` is negative and `it` reaches `end` while `it` points t a trail byte of a UTF-8 sequence, a `utf8::invalid_code_point` exception is thrown.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars;
+advance (w, 2, twochars + 6);
+assert (w == twochars + 5);
+advance (w, -2, twochars);
+assert (w == twochars);
+```
+
+In case of an invalid code point, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::distance
+
+Available in version 1.0 and later.
+
+Given the iterators to two UTF-8 encoded code points in a seqence, returns the number of code points between them.
+
+```cpp
+template <typename octet_iterator>
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+```
+
+`octet_iterator`: an input iterator.
+`first`: an iterator to a beginning of a UTF-8 encoded code point.
+`last`: an iterator to a "post-end" of the last UTF-8 encoded code point in the sequence we are trying to determine the length. It can be the beginning of a new code point, or not.
+ Return value the distance between the iterators, in code points.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::distance(twochars, twochars + 5);
+assert (dist == 2);
+```
+
+This function is used to find the length (in code points) of a UTF-8 encoded string. The reason it is called _distance_, rather than, say, _length_ is mainly because developers are used that _length_ is an O(1) function. Computing the length of an UTF-8 string is a linear operation, and it looked better to model it after `std::distance` algorithm.
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown. If `last` does not point to the past-of-end of a UTF-8 seqence, a `utf8::not_enough_room` exception is thrown.
+
+#### utf8::utf16to8
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+std::string utf16to8(const std::u16string& s);
+```
+
+`s`: a UTF-16 encoded string.
+Return value: A UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string u = utf16to8(utf16string);
+ assert (u.size() == 10);
+```
+
+In case of invalid UTF-16 sequence, a `utf8::invalid_utf16` exception is thrown.
+
+#### utf8::utf16to8
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+std::string utf16to8(std::u16string_view s);
+```
+
+`s`: a UTF-16 encoded string.
+Return value: A UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ u16string_view utf16stringview(u16string);
+ string u = utf16to8(utf16string);
+ assert (u.size() == 10);
+```
+
+In case of invalid UTF-16 sequence, a `utf8::invalid_utf16` exception is thrown.
+
+
+#### utf8::utf16to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+```
+
+`u16bit_iterator`: an input iterator.
+`octet_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-16 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-16 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);
+```
+
+In case of invalid UTF-16 sequence, a `utf8::invalid_utf16` exception is thrown.
+
+#### utf8::utf8to16
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts an UTF-8 encoded string to UTF-16.
+
+```cpp
+std::u16string utf8to16(const std::string& s);
+```
+
+`s`: an UTF-8 encoded string to convert.
+Return value: A UTF-16 encoded string
+
+Example of use:
+
+```cpp
+string utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+u16string utf16result = utf8to16(utf8_with_surrogates);
+assert (utf16result.length() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::utf8to16
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts an UTF-8 encoded string to UTF-16.
+
+```cpp
+std::u16string utf8to16(std::string_view s);
+```
+
+`s`: an UTF-8 encoded string to convert.
+Return value: A UTF-16 encoded string
+
+Example of use:
+
+```cpp
+string_view utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+u16string utf16result = utf8to16(utf8_with_surrogates);
+assert (utf16result.length() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+
+#### utf8::utf8to16
+
+Available in version 1.0 and later.
+
+Converts an UTF-8 encoded string to UTF-16
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+```
+
+`octet_iterator`: an input iterator.
+`u16bit_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert. < br /> `end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-16 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-16 string.
+
+Example of use:
+
+```cpp
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown. If `end` does not point to the past-of-end of a UTF-8 seqence, a `utf8::not_enough_room` exception is thrown.
+
+#### utf8::utf32to8
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+std::string utf32to8(const std::u32string& s);
+```
+
+`s`: a UTF-32 encoded string.
+Return value: a UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+u32string utf32string = {0x448, 0x65E5, 0x10346};
+string utf8result = utf32to8(utf32string);
+assert (utf8result.size() == 9);
+```
+
+In case of invalid UTF-32 string, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::utf32to8
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+std::string utf32to8(std::u32string_view s);
+```
+
+`s`: a UTF-32 encoded string.
+Return value: a UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+u32string utf32string = {0x448, 0x65E5, 0x10346};
+u32string_view utf32stringview(utf32string);
+string utf8result = utf32to8(utf32stringview);
+assert (utf8result.size() == 9);
+```
+
+In case of invalid UTF-32 string, a `utf8::invalid_code_point` exception is thrown.
+
+
+#### utf8::utf32to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+```
+
+`octet_iterator`: an output iterator.
+`u32bit_iterator`: an input iterator.
+`start`: an iterator pointing to the beginning of the UTF-32 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-32 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+```
+
+In case of invalid UTF-32 string, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::utf8to32
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+std::u32string utf8to32(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: a UTF-32 encoded string.
+
+Example of use:
+
+```cpp
+const char* twochars = "\xe6\x97\xa5\xd1\x88";
+u32string utf32result = utf8to32(twochars);
+assert (utf32result.size() == 2);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::utf8to32
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+std::u32string utf8to32(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: a UTF-32 encoded string.
+
+Example of use:
+
+```cpp
+string_view twochars = "\xe6\x97\xa5\xd1\x88";
+u32string utf32result = utf8to32(twochars);
+assert (utf32result.size() == 2);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+
+#### utf8::utf8to32
+
+Available in version 1.0 and later.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+```
+
+`octet_iterator`: an input iterator.
+`u32bit_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-32 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-32 string.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown. If `end` does not point to the past-of-end of a UTF-8 seqence, a `utf8::not_enough_room` exception is thrown.
+
+#### utf8::find_invalid
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Detects an invalid sequence within a UTF-8 string.
+
+```cpp
+std::size_t find_invalid(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: the index of the first invalid octet in the UTF-8 string. In case none were found, equals `std::string::npos`.
+
+Example of use:
+
+```cpp
+string utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+auto invalid = find_invalid(utf_invalid);
+assert (invalid == 5);
+```
+
+This function is typically used to make sure a UTF-8 string is valid before processing it with other functions. It is especially important to call it if before doing any of the _unchecked_ operations on it.
+
+#### utf8::find_invalid
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Detects an invalid sequence within a UTF-8 string.
+
+```cpp
+std::size_t find_invalid(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: the index of the first invalid octet in the UTF-8 string. In case none were found, equals `std::string_view::npos`.
+
+Example of use:
+
+```cpp
+string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+auto invalid = find_invalid(utf_invalid);
+assert (invalid == 5);
+```
+
+This function is typically used to make sure a UTF-8 string is valid before processing it with other functions. It is especially important to call it if before doing any of the _unchecked_ operations on it.
+
+
+#### utf8::find_invalid
+
+Available in version 1.0 and later.
+
+Detects an invalid sequence within a UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to test for validity.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to test for validity.
+Return value: an iterator pointing to the first invalid octet in the UTF-8 string. In case none were found, equals `end`.
+
+Example of use:
+
+```cpp
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
+assert (invalid == utf_invalid + 5);
+```
+
+This function is typically used to make sure a UTF-8 string is valid before processing it with other functions. It is especially important to call it if before doing any of the _unchecked_ operations on it.
+
+#### utf8::is_valid
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Checks whether a string object contains valid UTF-8 encoded text.
+
+```cpp
+bool is_valid(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string contains valid UTF-8 encoded text; `false` if not.
+
+Example of use:
+
+```cpp
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid);
+assert (bvalid == false);
+```
+
+You may want to use `is_valid` to make sure that a string contains valid UTF-8 text without the need to know where it fails if it is not valid.
+
+#### utf8::is_valid
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Checks whether a string object contains valid UTF-8 encoded text.
+
+```cpp
+bool is_valid(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string contains valid UTF-8 encoded text; `false` if not.
+
+Example of use:
+
+```cpp
+string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid);
+assert (bvalid == false);
+```
+
+You may want to use `is_valid` to make sure that a string contains valid UTF-8 text without the need to know where it fails if it is not valid.
+
+
+#### utf8::is_valid
+
+Available in version 1.0 and later.
+
+Checks whether a sequence of octets is a valid UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+bool is_valid(octet_iterator start, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to test for validity.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to test for validity.
+Return value: `true` if the sequence is a valid UTF-8 string; `false` if not.
+
+Example of use:
+
+```cpp
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
+assert (bvalid == false);
+```
+
+`is_valid` is a shorthand for `find_invalid(start, end) == end;`. You may want to use it to make sure that a byte seqence is a valid UTF-8 string without the need to know where it fails if it is not valid.
+
+#### utf8::replace_invalid
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+std::string replace_invalid(const std::string& s, char32_t replacement);
+std::string replace_invalid(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: A UTF-8 encoded string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+string invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+bvalid = is_valid(replace_invalid_result);
+assert (bvalid);
+const string fixed_invalid_sequence = "a????z";
+assert (fixed_invalid_sequence == replace_invalid_result);
+```
+
+#### utf8::replace_invalid
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+std::string replace_invalid(std::string_view s, char32_t replacement);
+std::string replace_invalid(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: A UTF-8 encoded string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+string_view invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+bool bvalid = is_valid(replace_invalid_result);
+assert (bvalid);
+const string fixed_invalid_sequence = "a????z";
+assert(fixed_invalid_sequence, replace_invalid_result);
+```
+
+
+#### utf8::replace_invalid
+
+Available in version 2.0 and later.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+```
+
+`octet_iterator`: an input iterator.
+`output_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to look for invalid UTF-8 sequences.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to look for invalid UTF-8 sequences.
+`out`: An output iterator to the range where the result of replacement is stored.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: An iterator pointing to the place after the UTF-8 string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+vector<char> replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+char* fixed_invalid_sequence = "a????z";
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+```
+
+`replace_invalid` does not perform in-place replacement of invalid sequences. Rather, it produces a copy of the original string with the invalid sequences replaced with a replacement marker. Therefore, `out` must not be in the `[start, end]` range.
+
+#### utf8::starts_with_bom
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Checks whether a string starts with a UTF-8 byte order mark (BOM)
+
+```cpp
+bool starts_with_bom(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string starts with a UTF-8 byte order mark; `false` if not.
+
+Example of use:
+
+```cpp
+string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+bool bbom = starts_with_bom(byte_order_mark);
+assert (bbom == true);
+string threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+bool no_bbom = starts_with_bom(threechars);
+assert (no_bbom == false);
+ ```
+
+The typical use of this function is to check the first three bytes of a file. If they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 encoded text.
+
+
+#### utf8::starts_with_bom
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Checks whether a string starts with a UTF-8 byte order mark (BOM)
+
+```cpp
+bool starts_with_bom(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string starts with a UTF-8 byte order mark; `false` if not.
+
+Example of use:
+
+```cpp
+string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+string_view byte_order_mark_view(byte_order_mark);
+bool bbom = starts_with_bom(byte_order_mark_view);
+assert (bbom);
+string_view threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+bool no_bbom = starts_with_bom(threechars);
+assert (!no_bbom);
+ ```
+
+The typical use of this function is to check the first three bytes of a file. If they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 encoded text.
+
+
+#### utf8::starts_with_bom
+
+Available in version 2.3 and later.
+
+Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
+
+```cpp
+template <typename octet_iterator>
+bool starts_with_bom (octet_iterator it, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`it`: beginning of the octet sequence to check
+`end`: pass-end of the sequence to check
+Return value: `true` if the sequence starts with a UTF-8 byte order mark; `false` if not.
+
+Example of use:
+
+```cpp
+unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+bool bbom = starts_with_bom(byte_order_mark, byte_order_mark + sizeof(byte_order_mark));
+assert (bbom == true);
+```
+
+The typical use of this function is to check the first three bytes of a file. If they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 encoded text.
+
+### Types From utf8 Namespace
+
+#### utf8::exception
+
+Available in version 2.3 and later.
+
+Base class for the exceptions thrown by UTF CPP library functions.
+
+```cpp
+class exception : public std::exception {};
+```
+
+Example of use:
+
+```cpp
+try {
+ code_that_uses_utf_cpp_library();
+}
+catch(const utf8::exception& utfcpp_ex) {
+ cerr << utfcpp_ex.what();
+}
+```
+
+#### utf8::invalid_code_point
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP functions such as `advance` and `next` if an UTF-8 sequence represents and invalid code point.
+
+```cpp
+class invalid_code_point : public exception {
+public:
+ uint32_t code_point() const;
+};
+```
+
+Member function `code_point()` can be used to determine the invalid code point that caused the exception to be thrown.
+
+#### utf8::invalid_utf8
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP functions such as `next` and `prior` if an invalid UTF-8 sequence is detected during decoding.
+
+```cpp
+class invalid_utf8 : public exception {
+public:
+ uint8_t utf8_octet() const;
+};
+```
+
+Member function `utf8_octet()` can be used to determine the beginning of the byte sequence that caused the exception to be thrown.
+
+#### utf8::invalid_utf16
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP function `utf16to8` if an invalid UTF-16 sequence is detected during decoding.
+
+```cpp
+class invalid_utf16 : public exception {
+public:
+ uint16_t utf16_word() const;
+};
+```
+
+Member function `utf16_word()` can be used to determine the UTF-16 code unit that caused the exception to be thrown.
+
+#### utf8::not_enough_room
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP functions such as `next` if the end of the decoded UTF-8 sequence was reached before the code point was decoded.
+
+```cpp
+class not_enough_room : public exception {};
+```
+
+#### utf8::iterator
+
+Available in version 2.0 and later.
+
+Adapts the underlying octet iterator to iterate over the sequence of code points, rather than raw octets.
+
+```cpp
+template <typename octet_iterator>
+class iterator;
+```
+
+##### Member functions
+
+`iterator();` the deafult constructor; the underlying octet_iterator is constructed with its default constructor.
+
+`explicit iterator (const octet_iterator& octet_it, const octet_iterator& range_start, const octet_iterator& range_end);` a constructor that initializes the underlying octet_iterator with octet_it and sets the range in which the iterator is considered valid.
+
+`octet_iterator base () const;` returns the underlying octet_iterator.
+
+`uint32_t operator * () const;` decodes the utf-8 sequence the underlying octet_iterator is pointing to and returns the code point.
+
+`bool operator == (const iterator& rhs) const;` returns `true` if the two underlaying iterators are equal.
+
+`bool operator != (const iterator& rhs) const;` returns `true` if the two underlaying iterators are not equal.
+
+`iterator& operator ++ ();` the prefix increment - moves the iterator to the next UTF-8 encoded code point.
+
+`iterator operator ++ (int);` the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+
+`iterator& operator -- ();` the prefix decrement - moves the iterator to the previous UTF-8 encoded code point.
+
+`iterator operator -- (int);` the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+
+Example of use:
+
+```cpp
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::iterator<char*> it(threechars, threechars, threechars + 9);
+utf8::iterator<char*> it2 = it;
+assert (it2 == it);
+assert (*it == 0x10346);
+assert (*(++it) == 0x65e5);
+assert ((*it++) == 0x65e5);
+assert (*it == 0x0448);
+assert (it != it2);
+utf8::iterator<char*> endit (threechars + 9, threechars, threechars + 9);
+assert (++it == endit);
+assert (*(--it) == 0x0448);
+assert ((*it--) == 0x0448);
+assert (*it == 0x65e5);
+assert (--it == utf8::iterator<char*>(threechars, threechars, threechars + 9));
+assert (*it == 0x10346);
+```
+
+The purpose of `utf8::iterator` adapter is to enable easy iteration as well as the use of STL algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of `utf8::next()` and `utf8::prior()` functions.
+
+Note that `utf8::iterator` adapter is a checked iterator. It operates on the range specified in the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically, the range will be determined by sequence container functions `begin` and `end`, i.e.:
+
+```cpp
+std::string s = "example";
+utf8::iterator i (s.begin(), s.begin(), s.end());
+```
+
+### Functions From utf8::unchecked Namespace
+
+#### utf8::unchecked::append
+
+Available in version 1.0 and later.
+
+Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence to a UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+```
+
+`cp`: A 32 bit integer representing a code point to append to the sequence.
+`result`: An output iterator to the place in the sequence where to append the code point.
+Return value: An iterator pointing to the place after the newly appended sequence.
+
+Example of use:
+
+```cpp
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = unchecked::append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+```
+
+This is a faster but less safe version of `utf8::append`. It does not check for validity of the supplied code point, and may produce an invalid UTF-8 sequence.
+
+#### utf8::unchecked::next
+
+Available in version 1.0 and later.
+
+Given the iterator to the beginning of a UTF-8 sequence, it returns the code point and moves the iterator to the next position.
+
+```cpp
+template <typename octet_iterator>
+uint32_t next(octet_iterator& it);
+```
+
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the beginning of the next code point.
+ Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::next(w);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+```
+
+This is a faster but less safe version of `utf8::next`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::peek_next
+
+Available in version 2.1 and later.
+
+Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
+
+```cpp
+template <typename octet_iterator>
+uint32_t peek_next(octet_iterator it);
+```
+
+`it`: an iterator pointing to the beginning of an UTF-8 encoded code point.
+Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::peek_next(w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+This is a faster but less safe version of `utf8::peek_next`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::prior
+
+Available in version 1.02 and later.
+
+Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it decreases the iterator until it hits the beginning of the previous UTF-8 encoded code point and returns the 32 bits representation of the code point.
+
+```cpp
+template <typename octet_iterator>
+uint32_t prior(octet_iterator& it);
+```
+
+`it`: a reference pointing to an octet within a UTF-8 encoded string. After the function returns, it is decremented to point to the beginning of the previous code point.
+ Return value: the 32 bit representation of the previous code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars + 3;
+int cp = unchecked::prior (w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+This is a faster but less safe version of `utf8::prior`. It does not check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+
+#### utf8::unchecked::advance
+
+Available in version 1.0 and later.
+
+Advances an iterator by the specified number of code points within an UTF-8 sequence.
+
+```cpp
+template <typename octet_iterator, typename distance_type>
+void advance (octet_iterator& it, distance_type n);
+```
+
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the nth following code point.
+`n`: number of code points `it` should be advanced. A negative value means decrement.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+unchecked::advance (w, 2);
+assert (w == twochars + 5);
+```
+
+This is a faster but less safe version of `utf8::advance`. It does not check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+
+#### utf8::unchecked::distance
+
+Available in version 1.0 and later.
+
+Given the iterators to two UTF-8 encoded code points in a seqence, returns the number of code points between them.
+
+```cpp
+template <typename octet_iterator>
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+```
+
+`first`: an iterator to a beginning of a UTF-8 encoded code point.
+`last`: an iterator to a "post-end" of the last UTF-8 encoded code point in the sequence we are trying to determine the length. It can be the beginning of a new code point, or not.
+Return value: the distance between the iterators, in code points.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
+assert (dist == 2);
+```
+
+This is a faster but less safe version of `utf8::distance`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::utf16to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-16 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-16 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+unchecked::utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);
+```
+
+This is a faster but less safe version of `utf8::utf16to8`. It does not check for validity of the supplied UTF-16 sequence.
+
+#### utf8::unchecked::utf8to16
+
+Available in version 1.0 and later.
+
+Converts an UTF-8 encoded string to UTF-16
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert. < br /> `end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-16 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-16 string.
+
+Example of use:
+
+```cpp
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+This is a faster but less safe version of `utf8::utf8to16`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::utf32to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-32 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-32 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+int utf32string[] = {0x448, 0x65e5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+```
+
+This is a faster but less safe version of `utf8::utf32to8`. It does not check for validity of the supplied UTF-32 sequence.
+
+#### utf8::unchecked::utf8to32
+
+Available in version 1.0 and later.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-32 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-32 string.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+unchecked::utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+```
+
+This is a faster but less safe version of `utf8::utf8to32`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::replace_invalid
+
+Available in version 3.1 and later.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+```
+
+`octet_iterator`: an input iterator.
+`output_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to look for invalid UTF-8 sequences.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to look for invalid UTF-8 sequences.
+`out`: An output iterator to the range where the result of replacement is stored.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: An iterator pointing to the place after the UTF-8 string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+vector<char> replace_invalid_result;
+unchecked::replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
+bvalid = utf8::is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+char* fixed_invalid_sequence = "a????z";
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+```
+
+`replace_invalid` does not perform in-place replacement of invalid sequences. Rather, it produces a copy of the original string with the invalid sequences replaced with a replacement marker. Therefore, `out` must not be in the `[start, end]` range.
+
+Unlike `utf8::replace_invalid`, this function does not verify validity of the replacement marker.
+
+### Types From utf8::unchecked Namespace
+
+#### utf8::iterator
+
+Available in version 2.0 and later.
+
+Adapts the underlying octet iterator to iterate over the sequence of code points, rather than raw octets.
+
+```cpp
+template <typename octet_iterator>
+class iterator;
+```
+
+##### Member functions
+
+`iterator();` the deafult constructor; the underlying octet_iterator is constructed with its default constructor.
+
+`explicit iterator (const octet_iterator& octet_it);` a constructor that initializes the underlying octet_iterator with `octet_it`.
+
+`octet_iterator base () const;` returns the underlying octet_iterator.
+
+`uint32_t operator * () const;` decodes the utf-8 sequence the underlying octet_iterator is pointing to and returns the code point.
+
+`bool operator == (const iterator& rhs) const;` returns `true` if the two underlaying iterators are equal.
+
+`bool operator != (const iterator& rhs) const;` returns `true` if the two underlaying iterators are not equal.
+
+`iterator& operator ++ ();` the prefix increment - moves the iterator to the next UTF-8 encoded code point.
+
+`iterator operator ++ (int);` the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+
+`iterator& operator -- ();` the prefix decrement - moves the iterator to the previous UTF-8 encoded code point.
+
+`iterator operator -- (int);` the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+
+Example of use:
+
+```cpp
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::unchecked::iterator<char*> un_it(threechars);
+utf8::unchecked::iterator<char*> un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == 0x10346);
+assert (*(++un_it) == 0x65e5);
+assert ((*un_it++) == 0x65e5);
+assert (*un_it == 0x0448);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator<char*> un_endit (threechars + 9);
+assert (++un_it == un_endit);
+assert (*(--un_it) == 0x0448);
+assert ((*un_it--) == 0x0448);
+assert (*un_it == 0x65e5);
+assert (--un_it == utf8::unchecked::iterator<char*>(threechars));
+assert (*un_it == 0x10346);
+```
+
+This is an unchecked version of `utf8::iterator`. It is faster in many cases, but offers no validity or range checks.
+
+## Links
+
+1. [The Unicode Consortium](http://www.unicode.org/).
+2. [ICU Library](http://icu.sourceforge.net/).
+3. [UTF-8 at Wikipedia](http://en.wikipedia.org/wiki/UTF-8)
+4. [UTF-8 and Unicode FAQ for Unix/Linux](http://www.cl.cam.ac.uk/~mgk25/unicode.html)
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp
new file mode 100644
index 0000000000..6533887253
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp
@@ -0,0 +1,64 @@
+#include "../source/utf8.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+
+using namespace std;
+
+int main(int argc, char** argv)
+{
+ if (argc != 2) {
+ cout << "\nUsage: docsample filename\n";
+ return 0;
+ }
+ const char* test_file_path = argv[1];
+ // Open the test file (must be UTF-8 encoded)
+ ifstream fs8(test_file_path);
+ if (!fs8.is_open()) {
+ cout << "Could not open " << test_file_path << endl;
+ return 0;
+ }
+
+ unsigned line_count = 1;
+ string line;
+ // Play with all the lines in the file
+ while (getline(fs8, line)) {
+ // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
+#if __cplusplus >= 201103L // C++ 11 or later
+ auto end_it = utf8::find_invalid(line.begin(), line.end());
+#else
+ string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+#endif // C++ 11
+ if (end_it != line.end()) {
+ cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
+ cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
+ }
+ // Get the line length (at least for the valid part)
+ ptrdiff_t length = utf8::distance(line.begin(), end_it);
+ cout << "Length of line " << line_count << " is " << length << "\n";
+
+ // Convert it to utf-16
+#if __cplusplus >= 201103L // C++ 11 or later
+ u16string utf16line = utf8::utf8to16(line);
+#else
+ vector<unsigned short> utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+#endif // C++ 11
+ // And back to utf-8;
+#if __cplusplus >= 201103L // C++ 11 or later
+ string utf8line = utf8::utf16to8(utf16line);
+#else
+ string utf8line;
+ utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+#endif // C++ 11
+ // Confirm that the conversion went OK:
+ if (utf8line != string(line.begin(), end_it))
+ cout << "Error in UTF-16 conversion at line: " << line_count << "\n";
+
+ line_count++;
+ }
+
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h
new file mode 100644
index 0000000000..82b13f59f9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h
@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h
new file mode 100644
index 0000000000..993b7f7c5f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h
@@ -0,0 +1,335 @@
+// Copyright 2006-2016 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_t cp;
+ public:
+ invalid_code_point(uint32_t codepoint) : cp(codepoint) {}
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid code point"; }
+ uint32_t code_point() const {return cp;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_t u8;
+ public:
+ invalid_utf8 (uint8_t u) : u8(u) {}
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-8"; }
+ uint8_t utf8_octet() const {return u8;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_t u16;
+ public:
+ invalid_utf16 (uint16_t u) : u16(u) {}
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-16"; }
+ uint16_t utf16_word() const {return u16;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Not enough space"; }
+ };
+
+ /// The library API - functions intended to be called by the users
+
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (!utf8::internal::is_code_point_valid(cp))
+ throw invalid_code_point(cp);
+
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ out = utf8::append (replacement, out);
+ start = end;
+ break;
+ case internal::INVALID_LEAD:
+ out = utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it, octet_iterator end)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it, octet_iterator end)
+ {
+ return utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it, octet_iterator start)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ return utf8::peek_next(it, end);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n, octet_iterator end)
+ {
+ const distance_type zero(0);
+ if (n < zero) {
+ // backward
+ for (distance_type i = n; i < zero; ++i)
+ utf8::prior(it, end);
+ } else {
+ // forward
+ for (distance_type i = zero; i < n; ++i)
+ utf8::next(it, end);
+ }
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ if (utf8::internal::is_trail_surrogate(trail_surrogate))
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ else
+ throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::next(start, end);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ typedef uint32_t value_type;
+ typedef uint32_t* pointer;
+ typedef uint32_t& reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it,
+ const octet_iterator& rangestart,
+ const octet_iterator& rangeend) :
+ it(octet_it), range_start(rangestart), range_end(rangeend)
+ {
+ if (it < range_start || it > range_end)
+ throw std::out_of_range("Invalid utf-8 iterator position");
+ }
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#if UTF_CPP_CPLUSPLUS >= 201703L // C++ 17 or later
+#include "cpp17.h"
+#elif UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
+#include "cpp11.h"
+#endif // C++ 11 or later
+
+#endif //header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h
new file mode 100644
index 0000000000..de6199f2a3
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h
@@ -0,0 +1,338 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+// Determine the C++ standard version.
+// If the user defines UTF_CPP_CPLUSPLUS, use that.
+// Otherwise, trust the unreliable predefined macro __cplusplus
+
+#if !defined UTF_CPP_CPLUSPLUS
+ #define UTF_CPP_CPLUSPLUS __cplusplus
+#endif
+
+#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
+ #define UTF_CPP_OVERRIDE override
+ #define UTF_CPP_NOEXCEPT noexcept
+#else // C++ 98/03
+ #define UTF_CPP_OVERRIDE
+ #define UTF_CPP_NOEXCEPT throw()
+#endif // C++ 11 or later
+
+
+namespace utf8
+{
+ // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+ // You may need to change them to match your system.
+ // These typedefs have the same names as ones from cstdint, or boost/cstdint
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+ // Unicode constants
+ // Leading (high) surrogates: 0xd800 - 0xdbff
+ // Trailing (low) surrogates: 0xdc00 - 0xdfff
+ const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
+ const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
+ const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+ const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+ const uint16_t LEAD_OFFSET = 0xd7c0u; // LEAD_SURROGATE_MIN - (0x10000 >> 10)
+ const uint32_t SURROGATE_OFFSET = 0xfca02400u; // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_t>(0xffff & oc);
+ }
+ template<typename octet_type>
+ inline bool is_trail(octet_type oc)
+ {
+ return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+ }
+
+ template <typename u16>
+ inline bool is_lead_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 cp)
+ {
+ return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+ }
+
+ template <typename octet_iterator>
+ inline typename std::iterator_traits<octet_iterator>::difference_type
+ sequence_length(octet_iterator lead_it)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// get_sequence_x functions decode utf-8 sequences of the length x
+ template <typename octet_iterator>
+ utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+ template <typename octet_iterator>
+ utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ // Save the original value of it so we can go back in case of failure
+ // Of course, it does not make much sense with i.e. stream iterators
+ octet_iterator original_it = it;
+
+ uint32_t cp = 0;
+ // Determine the sequence length based on the lead octet
+ typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+ const octet_difference_type length = utf8::internal::sequence_length(it);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h
new file mode 100644
index 0000000000..d93961b04f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h
@@ -0,0 +1,103 @@
+// Copyright 2018 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
+#define UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
+
+#include "checked.h"
+#include <string>
+
+namespace utf8
+{
+
+ inline void append(char32_t cp, std::string& s)
+ {
+ append(uint32_t(cp), std::back_inserter(s));
+ }
+
+ inline std::string utf16to8(const std::u16string& s)
+ {
+ std::string result;
+ utf16to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u16string utf8to16(const std::string& s)
+ {
+ std::u16string result;
+ utf8to16(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::string utf32to8(const std::u32string& s)
+ {
+ std::string result;
+ utf32to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u32string utf8to32(const std::string& s)
+ {
+ std::u32string result;
+ utf8to32(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::size_t find_invalid(const std::string& s)
+ {
+ std::string::const_iterator invalid = find_invalid(s.begin(), s.end());
+ return (invalid == s.end()) ? std::string::npos : (invalid - s.begin());
+ }
+
+ inline bool is_valid(const std::string& s)
+ {
+ return is_valid(s.begin(), s.end());
+ }
+
+ inline std::string replace_invalid(const std::string& s, char32_t replacement)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
+ return result;
+ }
+
+ inline std::string replace_invalid(const std::string& s)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline bool starts_with_bom(const std::string& s)
+ {
+ return starts_with_bom(s.begin(), s.end());
+ }
+
+} // namespace utf8
+
+#endif // header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h
new file mode 100644
index 0000000000..7bfa869942
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h
@@ -0,0 +1,103 @@
+// Copyright 2018 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
+#define UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
+
+#include "checked.h"
+#include <string>
+
+namespace utf8
+{
+
+ inline void append(char32_t cp, std::string& s)
+ {
+ append(uint32_t(cp), std::back_inserter(s));
+ }
+
+ inline std::string utf16to8(std::u16string_view s)
+ {
+ std::string result;
+ utf16to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u16string utf8to16(std::string_view s)
+ {
+ std::u16string result;
+ utf8to16(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::string utf32to8(std::u32string_view s)
+ {
+ std::string result;
+ utf32to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u32string utf8to32(std::string_view s)
+ {
+ std::u32string result;
+ utf8to32(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::size_t find_invalid(std::string_view s)
+ {
+ std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end());
+ return (invalid == s.end()) ? std::string_view::npos : (invalid - s.begin());
+ }
+
+ inline bool is_valid(std::string_view s)
+ {
+ return is_valid(s.begin(), s.end());
+ }
+
+ inline std::string replace_invalid(std::string_view s, char32_t replacement)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
+ return result;
+ }
+
+ inline std::string replace_invalid(std::string_view s)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline bool starts_with_bom(std::string_view s)
+ {
+ return starts_with_bom(s.begin(), s.end());
+ }
+
+} // namespace utf8
+
+#endif // header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h
new file mode 100644
index 0000000000..0e1b51cc7d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h
@@ -0,0 +1,274 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ out = utf8::unchecked::append (replacement, out);
+ start = end;
+ break;
+ case internal::INVALID_LEAD:
+ out = utf8::unchecked::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::unchecked::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::unchecked::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it)
+ {
+ uint32_t cp = utf8::internal::mask8(*it);
+ typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+ switch (length) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it)
+ {
+ while (utf8::internal::is_trail(*(--it))) ;
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n)
+ {
+ const distance_type zero(0);
+ if (n < zero) {
+ // backward
+ for (distance_type i = n; i < zero; ++i)
+ utf8::unchecked::prior(it);
+ } else {
+ // forward
+ for (distance_type i = zero; i < n; ++i)
+ utf8::unchecked::next(it);
+ }
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::unchecked::next(start);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator {
+ octet_iterator it;
+ public:
+ typedef uint32_t value_type;
+ typedef uint32_t* pointer;
+ typedef uint32_t& reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt
new file mode 100644
index 0000000000..4063df7c67
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt
@@ -0,0 +1,47 @@
+add_executable(negative ${PROJECT_SOURCE_DIR}/tests/negative.cpp)
+add_executable(cpp11 ${PROJECT_SOURCE_DIR}/tests/test_cpp11.cpp)
+add_executable(cpp17 ${PROJECT_SOURCE_DIR}/tests/test_cpp17.cpp)
+add_executable(apitests
+ ${PROJECT_SOURCE_DIR}/tests/test_checked_api.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_api.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_checked_iterator.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_iterator.cpp
+)
+
+add_executable(noexceptionstests
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_api.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_iterator.cpp
+)
+
+target_link_libraries(negative PRIVATE utf8::cpp)
+target_link_libraries(cpp11 PRIVATE utf8::cpp)
+target_link_libraries(cpp17 PRIVATE utf8::cpp)
+target_link_libraries(apitests PRIVATE utf8::cpp)
+target_link_libraries(noexceptionstests PRIVATE utf8::cpp)
+
+target_compile_options(noexceptionstests PUBLIC -fno-exceptions)
+
+set_target_properties(negative apitests noexceptionstests
+ PROPERTIES
+ CXX_STANDARD 98
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+set_target_properties(cpp11
+ PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+set_target_properties(cpp17
+ PROPERTIES
+ CXX_STANDARD 17
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+add_test(negative_test negative ${PROJECT_SOURCE_DIR}/tests/test_data/utf8_invalid.txt)
+add_test(cpp11_test cpp11)
+add_test(cpp17_test cpp17)
+add_test(api_test apitests)
+add_test(noexceptions_test noexceptionstests)
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile
new file mode 100644
index 0000000000..9df3717a1d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile
@@ -0,0 +1,5 @@
+FROM debian:buster-slim
+
+RUN apt-get update \
+ && apt-get install -y make g++ cmake git \
+ && rm -rf /var/lib/apt/lists/*
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp
new file mode 100644
index 0000000000..f1bcc993e0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp
@@ -0,0 +1,59 @@
+#include "utf8.h"
+using namespace utf8;
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+using namespace std;
+
+const unsigned INVALID_LINES[] = { 75, 76, 83, 84, 85, 93, 102, 103, 105, 106, 107, 108, 109, 110, 114, 115, 116, 117, 124, 125, 130, 135, 140, 145, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 169, 175, 176, 177, 207, 208, 209, 210, 211, 220, 221, 222, 223, 224, 232, 233, 234, 235, 236, 247, 248, 249, 250, 251, 252, 253, 257, 258, 259, 260, 261, 262, 263, 264};
+const unsigned* INVALID_LINES_END = INVALID_LINES + sizeof(INVALID_LINES)/sizeof(unsigned);
+
+int main(int argc, char** argv)
+{
+ string test_file_path;
+ if (argc == 2)
+ test_file_path = argv[1];
+ else {
+ cout << "Wrong number of arguments" << endl;
+ return 1;
+ }
+ // Open the test file
+ ifstream fs8(test_file_path.c_str());
+ if (!fs8.is_open()) {
+ cout << "Could not open " << test_file_path << endl;
+ return 1;
+ }
+
+ // Read it line by line
+ unsigned int line_count = 0;
+ char byte;
+ while (!fs8.eof()) {
+ string line;
+ while ((byte = static_cast<char>(fs8.get())) != '\n' && !fs8.eof())
+ line.push_back(byte);
+
+ line_count++;
+ bool expected_valid = (find(INVALID_LINES, INVALID_LINES_END, line_count) == INVALID_LINES_END);
+ // Print out lines that contain unexpected invalid UTF-8
+ if (!is_valid(line.begin(), line.end())) {
+ if (expected_valid) {
+ cout << "Unexpected invalid utf-8 at line " << line_count << '\n';
+ return 1;
+ }
+
+ // try fixing it:
+ string fixed_line;
+ replace_invalid(line.begin(), line.end(), back_inserter(fixed_line));
+ if (!is_valid(fixed_line.begin(), fixed_line.end())) {
+ cout << "replace_invalid() resulted in an invalid utf-8 at line " << line_count << '\n';
+ return 1;
+ }
+ }
+ else if (!expected_valid) {
+ cout << "Invalid utf-8 NOT detected at line " << line_count << '\n';
+ return 1;
+ }
+ }
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp
new file mode 100644
index 0000000000..b57e1bc894
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp
@@ -0,0 +1,189 @@
+#define F_TEST_NO_MAIN
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+
+#include <string>
+#include <vector>
+using namespace utf8;
+using namespace std;
+
+
+TEST(CheckedAPITests, test_append)
+{
+ unsigned char u[5] = {0,0,0,0,0};
+ append(0x0448, u);
+ EXPECT_EQ (u[0], 0xd1);
+ EXPECT_EQ (u[1], 0x88);
+ EXPECT_EQ (u[2], 0);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x65e5, u);
+ EXPECT_EQ (u[0], 0xe6);
+ EXPECT_EQ (u[1], 0x97);
+ EXPECT_EQ (u[2], 0xa5);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x3044, u);
+ EXPECT_EQ (u[0], 0xe3);
+ EXPECT_EQ (u[1], 0x81);
+ EXPECT_EQ (u[2], 0x84);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x10346, u);
+ EXPECT_EQ (u[0], 0xf0);
+ EXPECT_EQ (u[1], 0x90);
+ EXPECT_EQ (u[2], 0x8d);
+ EXPECT_EQ (u[3], 0x86);
+ EXPECT_EQ (u[4], 0);
+}
+
+TEST(CheckedAPITests, test_next)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars;
+ int cp = next(w, twochars + 6);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars + 3);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars;
+
+ cp = next(w, threechars + 9);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars + 4);
+
+ cp = next(w, threechars + 9);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 7);
+
+ cp = next(w, threechars + 9);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 9);
+}
+
+TEST(CheckedAPITests, test_peek_next)
+{
+ const char* const cw = "\xe6\x97\xa5\xd1\x88";
+ int cp = peek_next(cw, cw + 6);
+ EXPECT_EQ (cp, 0x65e5);
+}
+
+TEST(CheckedAPITests, test_prior)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars + 3;
+ int cp = prior (w, twochars);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars + 9;
+ cp = prior(w, threechars);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 7);
+ cp = prior(w, threechars);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 4);
+ cp = prior(w, threechars);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars);
+}
+
+TEST(CheckedAPITests, test_advance)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ const char* w = threechars;
+ advance(w, 2, threechars + 9);
+ EXPECT_EQ(w, threechars + 7);
+ advance(w, -2, threechars);
+ EXPECT_EQ(w, threechars);
+ advance(w, 3, threechars + 9);
+ EXPECT_EQ(w, threechars + 9);
+ advance(w, -2, threechars);
+ EXPECT_EQ(w, threechars + 4);
+ advance(w, -1, threechars);
+ EXPECT_EQ(w, threechars);
+}
+
+TEST(CheckedAPITests, test_distance)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ size_t dist = utf8::distance(twochars, twochars + 5);
+ EXPECT_EQ (dist, 2);
+}
+
+TEST(CheckedAPITests, test_utf32to8)
+{
+ int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+ string utf8result;
+ utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(CheckedAPITests, test_utf8to32)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ vector<int> utf32result;
+ utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(CheckedAPITests, test_utf16to8)
+{
+ unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string utf8result;
+ utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 10);
+}
+
+TEST(CheckedAPITests, test_utf8to16)
+{
+ char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ vector <unsigned short> utf16result;
+ utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+}
+
+TEST(CheckedAPITests, test_replace_invalid)
+{
+ char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ vector<char> replace_invalid_result;
+ replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), std::back_inserter(replace_invalid_result), '?');
+ bool bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+ EXPECT_TRUE (bvalid);
+ const char fixed_invalid_sequence[] = "a????z";
+ EXPECT_EQ (sizeof(fixed_invalid_sequence), replace_invalid_result.size());
+ EXPECT_TRUE (std::equal(replace_invalid_result.begin(), replace_invalid_result.begin() + sizeof(fixed_invalid_sequence), fixed_invalid_sequence));
+}
+
+TEST(CheckedAPITests, test_find_invalid)
+{
+ char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+ char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
+ EXPECT_EQ (invalid, utf_invalid + 5);
+}
+
+TEST(CheckedAPITests, test_is_valid)
+{
+ char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+ bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
+ EXPECT_FALSE (bvalid);
+ char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ bvalid = is_valid(utf8_with_surrogates, utf8_with_surrogates + 9);
+ EXPECT_TRUE (bvalid);
+}
+
+TEST(CheckedAPITests, test_starts_with_bom)
+{
+ unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+ bool bbom = starts_with_bom(byte_order_mark, byte_order_mark + sizeof(byte_order_mark));
+ EXPECT_TRUE (bbom);
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ bool no_bbom = starts_with_bom(threechars, threechars + sizeof(threechars));
+ EXPECT_FALSE (no_bbom);
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp
new file mode 100644
index 0000000000..3f9bfe96a2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp
@@ -0,0 +1,32 @@
+#define F_TEST_NO_MAIN
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+
+using namespace utf8;
+
+
+TEST(CheckedIteratrTests, test_increment)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::iterator<const char*> it(threechars, threechars, threechars + 9);
+ utf8::iterator<const char*> it2 = it;
+ EXPECT_EQ (it2, it);
+ EXPECT_EQ (*it, 0x10346);
+ EXPECT_EQ (*(++it), 0x65e5);
+ EXPECT_EQ ((*it++), 0x65e5);
+ EXPECT_EQ (*it, 0x0448);
+ EXPECT_NE (it, it2);
+ utf8::iterator<const char*> endit (threechars + 9, threechars, threechars + 9);
+ EXPECT_EQ (++it, endit);
+}
+
+TEST(CheckedIteratrTests, test_decrement)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::iterator<const char*> it(threechars+9, threechars, threechars + 9);
+ EXPECT_EQ (*(--it), 0x0448);
+ EXPECT_EQ ((*it--), 0x0448);
+ EXPECT_EQ (*it, 0x65e5);
+ EXPECT_EQ (--it, utf8::iterator<const char*>(threechars, threechars, threechars + 9));
+ EXPECT_EQ (*it, 0x10346);
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp
new file mode 100644
index 0000000000..ee4ddd8fd6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp
@@ -0,0 +1,109 @@
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+#include <string>
+using namespace utf8;
+using namespace std;
+
+#if __cplusplus >= 201103L // C++ 11 or later
+
+TEST(CPP11APITests, test_append)
+{
+ string u;
+ append(0x0448, u);
+ EXPECT_EQ (u[0], char(0xd1));
+ EXPECT_EQ (u[1], char(0x88));
+ EXPECT_EQ (u.length(), 2);
+
+ u.clear();
+ append(0x65e5, u);
+ EXPECT_EQ (u[0], char(0xe6));
+ EXPECT_EQ (u[1], char(0x97));
+ EXPECT_EQ (u[2], char(0xa5));
+ EXPECT_EQ (u.length(), 3);
+
+ u.clear();
+ append(0x3044, u);
+ EXPECT_EQ (u[0], char(0xe3));
+ EXPECT_EQ (u[1], char(0x81));
+ EXPECT_EQ (u[2], char(0x84));
+ EXPECT_EQ (u.length(), 3);
+
+ u.clear();
+ append(0x10346, u);
+ EXPECT_EQ (u[0], char(0xf0));
+ EXPECT_EQ (u[1], char(0x90));
+ EXPECT_EQ (u[2], char(0x8d));
+ EXPECT_EQ (u[3], char(0x86));
+ EXPECT_EQ (u.length(), 4);
+}
+
+TEST(CPP11APITests, test_utf16to8)
+{
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string u = utf16to8(utf16string);
+ EXPECT_EQ (u.size(), 10);
+}
+
+TEST(CPP11APITests, test_utf8to16)
+{
+ string utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ u16string utf16result = utf8to16(utf8_with_surrogates);
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+ // Just to make sure it compiles with string literals
+ utf8to16(u8"simple");
+ utf8to16("simple");
+}
+
+TEST(CPP11APITests, test_utf32to8)
+{
+ u32string utf32string = {0x448, 0x65E5, 0x10346};
+ string utf8result = utf32to8(utf32string);
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(CPP11APITests, test_utf8to32)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ u32string utf32result = utf8to32(twochars);
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(CPP11APITests, test_find_invalid)
+{
+ string utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ auto invalid = find_invalid(utf_invalid);
+ EXPECT_EQ (invalid, 5);
+}
+
+TEST(CPP11APITests, test_is_valid)
+{
+ string utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ bool bvalid = is_valid(utf_invalid);
+ EXPECT_FALSE (bvalid);
+ string utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ bvalid = is_valid(utf8_with_surrogates);
+ EXPECT_TRUE (bvalid);
+}
+
+TEST(CPP11APITests, test_replace_invalid)
+{
+ string invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+ bool bvalid = is_valid(replace_invalid_result);
+ EXPECT_TRUE (bvalid);
+ const string fixed_invalid_sequence = "a????z";
+ EXPECT_EQ(fixed_invalid_sequence, replace_invalid_result);
+}
+
+TEST(CPP11APITests, test_starts_with_bom)
+{
+ string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+ bool bbom = starts_with_bom(byte_order_mark);
+ EXPECT_TRUE (bbom);
+ string threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ bool no_bbom = starts_with_bom(threechars);
+ EXPECT_FALSE (no_bbom);
+}
+#endif // C++ 11 or later
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp
new file mode 100644
index 0000000000..4b87816b1c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp
@@ -0,0 +1,88 @@
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+#include <string>
+using namespace utf8;
+using namespace std;
+
+#if __cplusplus >= 201703L // C++ 17 or later
+
+
+TEST(CPP17APITests, test_utf16to8)
+{
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ u16string_view utf16stringview(u16string);
+ string u = utf16to8(utf16string);
+ EXPECT_EQ (u.size(), 10);
+}
+
+TEST(CPP17APITests, test_utf8to16)
+{
+ string_view utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ u16string utf16result = utf8to16(utf8_with_surrogates);
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+}
+
+TEST(CPP17APITests, test_utf32to8)
+{
+ u32string utf32string = {0x448, 0x65E5, 0x10346};
+ u32string_view utf32stringview(utf32string);
+ string utf8result = utf32to8(utf32stringview);
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(CPP17APITests, test_utf8to32)
+{
+ string_view twochars = "\xe6\x97\xa5\xd1\x88";
+ u32string utf32result = utf8to32(twochars);
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(CPP17APITests, test_find_invalid)
+{
+ string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ auto invalid = find_invalid(utf_invalid);
+ EXPECT_EQ (invalid, 5);
+}
+
+TEST(CPP17APITests, test_is_valid)
+{
+ string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ bool bvalid = is_valid(utf_invalid);
+ EXPECT_FALSE (bvalid);
+ string_view utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ bvalid = is_valid(utf8_with_surrogates);
+ EXPECT_TRUE (bvalid);
+}
+
+TEST(CPP17APITests, test_replace_invalid)
+{
+ string_view invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+ bool bvalid = is_valid(replace_invalid_result);
+ EXPECT_TRUE (bvalid);
+ const string fixed_invalid_sequence = "a????z";
+ EXPECT_EQ(fixed_invalid_sequence, replace_invalid_result);
+}
+
+TEST(CPP17APITests, test_starts_with_bom)
+{
+ string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+ string_view byte_order_mark_view(byte_order_mark);
+ bool bbom = starts_with_bom(byte_order_mark_view);
+ EXPECT_TRUE (bbom);
+ string_view threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ bool no_bbom = starts_with_bom(threechars);
+ EXPECT_FALSE (no_bbom);
+}
+
+TEST(CPP17APITests, string_class_and_literals)
+{
+ const char* twochars = u8"ab";
+ EXPECT_TRUE (is_valid(twochars));
+ const string two_chars_string(twochars);
+ EXPECT_TRUE (is_valid(two_chars_string));
+}
+
+#endif // C++ 11 or later
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txt b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txt
new file mode 100644
index 0000000000..ae83159328
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txt
Binary files differ
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp
new file mode 100644
index 0000000000..c400ada0d2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp
@@ -0,0 +1,161 @@
+#include "../extern/ftest/ftest.h"
+#include "utf8/unchecked.h"
+
+#include <string>
+#include <vector>
+using namespace utf8::unchecked;
+using namespace std;
+
+TEST(UnCheckedAPITests, test_append)
+{
+ unsigned char u[5] = {0,0,0,0,0};
+ append(0x0448, u);
+ EXPECT_EQ (u[0], 0xd1);
+ EXPECT_EQ (u[1], 0x88);
+ EXPECT_EQ (u[2], 0);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x65e5, u);
+ EXPECT_EQ (u[0], 0xe6);
+ EXPECT_EQ (u[1], 0x97);
+ EXPECT_EQ (u[2], 0xa5);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x3044, u);
+ EXPECT_EQ (u[0], 0xe3);
+ EXPECT_EQ (u[1], 0x81);
+ EXPECT_EQ (u[2], 0x84);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x10346, u);
+ EXPECT_EQ (u[0], 0xf0);
+ EXPECT_EQ (u[1], 0x90);
+ EXPECT_EQ (u[2], 0x8d);
+ EXPECT_EQ (u[3], 0x86);
+ EXPECT_EQ (u[4], 0);
+}
+
+TEST(UnCheckedAPITests, test_next)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars;
+ int cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars + 3);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars;
+
+ cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars + 4);
+
+ cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 7);
+
+ cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 9);
+}
+
+TEST(UnCheckedAPITests, test_peek_next)
+{
+ const char* const cw = "\xe6\x97\xa5\xd1\x88";
+ int cp = peek_next(cw);
+ EXPECT_EQ (cp, 0x65e5);
+}
+
+TEST(UnCheckedAPITests, test_prior)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars + 3;
+ int cp = prior (w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars + 9;
+ cp = prior(w);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 7);
+ cp = prior(w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 4);
+ cp = prior(w);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars);
+}
+
+TEST(UnCheckedAPITests, test_advance)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ const char* w = threechars;
+ utf8::unchecked::advance(w, 2);
+ EXPECT_EQ(w, threechars + 7);
+ utf8::unchecked::advance(w, -2);
+ EXPECT_EQ(w, threechars);
+ utf8::unchecked::advance(w, 3);
+ EXPECT_EQ(w, threechars + 9);
+ utf8::unchecked::advance(w, -2);
+ EXPECT_EQ(w, threechars + 4);
+ utf8::unchecked::advance(w, -1);
+ EXPECT_EQ(w, threechars);
+}
+
+TEST(UnCheckedAPITests, test_distance)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
+ EXPECT_EQ (dist, 2);
+}
+
+TEST(UnCheckedAPITests, test_utf32to8)
+{
+ int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+ string utf8result;
+ utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(UnCheckedAPITests, test_utf8to32)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ vector<int> utf32result;
+ utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(UnCheckedAPITests, test_utf16to8)
+{
+ unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string utf8result;
+ utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 10);
+}
+
+TEST(UnCheckedAPITests, test_utf8to16)
+{
+ char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ vector <unsigned short> utf16result;
+ utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+}
+
+TEST(UnCheckedAPITests, test_replace_invalid)
+{
+ char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ vector<char> replace_invalid_result;
+ replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), std::back_inserter(replace_invalid_result), '?');
+ bool bvalid = utf8::is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+ EXPECT_TRUE (bvalid);
+ const char fixed_invalid_sequence[] = "a????z";
+ EXPECT_EQ (sizeof(fixed_invalid_sequence), replace_invalid_result.size());
+ EXPECT_TRUE (std::equal(replace_invalid_result.begin(), replace_invalid_result.begin() + sizeof(fixed_invalid_sequence), fixed_invalid_sequence));
+}
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp
new file mode 100644
index 0000000000..68943bf94c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp
@@ -0,0 +1,34 @@
+#define F_TEST_NO_MAIN
+#include "../extern/ftest/ftest.h"
+
+#include "utf8/unchecked.h"
+
+using namespace utf8::unchecked;
+
+
+TEST(UnCheckedIteratrTests, test_increment)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::unchecked::iterator<const char*> it(threechars);
+ utf8::unchecked::iterator<const char*> it2 = it;
+ EXPECT_EQ (it2, it);
+ EXPECT_EQ (*it, 0x10346);
+ EXPECT_EQ (*(++it), 0x65e5);
+ EXPECT_EQ ((*it++), 0x65e5);
+ EXPECT_EQ (*it, 0x0448);
+ EXPECT_NE (it, it2);
+ utf8::unchecked::iterator<const char*> endit (threechars + 9);
+ EXPECT_EQ (++it, endit);
+}
+
+TEST(UnCheckedIteratrTests, test_decrement)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::unchecked::iterator<const char*> it(threechars+9);
+ EXPECT_EQ (*(--it), 0x0448);
+ EXPECT_EQ ((*it--), 0x0448);
+ EXPECT_EQ (*it, 0x65e5);
+ EXPECT_EQ (--it, utf8::unchecked::iterator<const char*>(threechars));
+ EXPECT_EQ (*it, 0x10346);
+
+}