summaryrefslogtreecommitdiffstats
path: root/comm/third_party/rnp/src/libsexp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/rnp/src/libsexp')
-rw-r--r--comm/third_party/rnp/src/libsexp/LICENSE.md34
-rw-r--r--comm/third_party/rnp/src/libsexp/README.adoc195
-rw-r--r--comm/third_party/rnp/src/libsexp/include/sexp/ext-key-format.h99
-rw-r--r--comm/third_party/rnp/src/libsexp/include/sexp/sexp-error.h77
-rw-r--r--comm/third_party/rnp/src/libsexp/include/sexp/sexp.h435
-rw-r--r--comm/third_party/rnp/src/libsexp/src/ext-key-format.cpp314
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-char-defs.cpp351
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-error.cpp62
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-input.cpp507
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-main.cpp237
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-object.cpp194
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-output.cpp208
-rw-r--r--comm/third_party/rnp/src/libsexp/src/sexp-simple-string.cpp197
-rw-r--r--comm/third_party/rnp/src/libsexp/version.txt1
14 files changed, 2911 insertions, 0 deletions
diff --git a/comm/third_party/rnp/src/libsexp/LICENSE.md b/comm/third_party/rnp/src/libsexp/LICENSE.md
new file mode 100644
index 0000000000..2e579d2074
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/LICENSE.md
@@ -0,0 +1,34 @@
+Original MIT License
+====================
+
+Copyright 1997 Ronald L. Rivest, Butler Lampson
+Copyright 1997 MIT Laboratory for Computer Science
+
+The code is available under the "MIT License" (open source).
+
+License text available at:
+https://opensource.org/licenses/MIT
+
+
+Ribose MIT License
+====================
+
+Copyright 2021-2022 Ribose Inc.
+
+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/comm/third_party/rnp/src/libsexp/README.adoc b/comm/third_party/rnp/src/libsexp/README.adoc
new file mode 100644
index 0000000000..69317257d4
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/README.adoc
@@ -0,0 +1,195 @@
+= S-expressions parser and generator library in C\++ (SEXP in C++)
+
+image:https://github.com/rnpgp/sexp/workflows/build-and-test/badge.svg["Build status Ubuntu/macOS/Windows", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test"]
+image:https://github.com/rnpgp/sexp/workflows/build-and-test-rh/badge.svg["Build status CentOS/Fedora", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test-rh"]
+image:https://github.com/rnpgp/sexp/workflows/build-and-test-deb/badge.svg["Build status Debian", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test-deb"]
+image:https://github.com/rnpgp/sexp/workflows/build-and-test-msys/badge.svg["Build status MSys", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test-msys"]
+
+
+image:https://codecov.io/gh/rnpgp/sexp/branch/feat/g23/graph/badge.svg["Code coverage", link="https://codecov.io/gh/rnpgp/sexp"]
+image:https://github.com/rnpgp/sexp/workflows/CodeQL/badge.svg["CodeQL analysis", link="https://github.com/rnpgp/sexp/actions?workflow=CodeQL"]
+image:https://scan.coverity.com/projects/27150/badge.svg["Coverity Scan Build Status", link="https://scan.coverity.com/projects/rnpgp-sexp"]
+
+
+== Purpose
+
+This is a C++ library for working with S-expressions. This implementation
+is derived from the reference SEXP C library developed by Professors Ronald Rivest
+and Butler Lampson of MIT LCS (now CSAIL).
+
+This library differs from the original C implementation in the following ways:
+
+* It aims to be reuseable in C++ implementations and is importable via CMake.
+* It includes a test suite for correctness testing and tests against malformed
+ S-expressions.
+* It supports, and is tested against, all major platforms, including:
+** Ubuntu, Debian, Fedora, CentOS
+** macOS
+** Windows
+** msys
+* It implements additional interface to work with S-expressions wrapped by GnuPG 2.3+ extended format as defined at https://github.com/gpg/gnupg/blob/master/agent/keyformat.txt
+
+The original C library is available at:
+
+* http://people.csail.mit.edu/rivest/sexp.html
+
+
+== Background
+
+S-expressions are a data structure for representing complex data as a variation
+on https://en.wikipedia.org/wiki/Lisp_(programming_language)[LISP] S-expressions.
+
+S-expressions were originally adopted for use in
+http://theory.lcs.mit.edu/~cis/sdsi.html[SDSI] and
+http://world.std.com/~cme/html/spki.html[SPKI].
+
+SDSI has been developed by Professors
+https://people.csail.mit.edu/rivest/index.html[Ronald L. Rivest] and Butler
+Lampson of http://www.lcs.mit.edu/[MIT's Laboratory for Computer Science],
+members of
+http://theory.lcs.mit.edu/~cis[LCS's Cryptography and Information Security]
+research group.
+
+NOTE: SDSI research has been supported by DARPA contract DABT63-96-C-0018,
+"Security for Distributed Computer Systems".
+
+NOTE: SPKI has been developed by
+http://www.clark.net/pub/cme/home.html[Carl Ellison] and others in the IETF SPKI
+working group.
+
+
+== Usage guide for S-expressions
+
+* https://people.csail.mit.edu/rivest/Sexp.txt[SEXP 1.0 guide]
+
+
+== Code
+
+The library is a deep rework to C++ of the original
+https://people.csail.mit.edu/rivest/sexp.html[SEXP library] that maintains full
+support of original specification.
+
+While most applications will not need anything but the simple canonical and
+transport formats; however, the code here is considerably more complex because
+it also supports the advanced format, both for input and for output.
+
+
+== Building and installation
+
+[source,sh]
+----
+mkdir build
+cd build
+cmake ..
+cmake --build .
+ctest
+cmake --install .
+----
+
+
+== CMake script options
+
+`WITH_SEXP_TESTS:BOOL`::
+build tests (default: `ON`)
+
+`DOWNLOAD_GTEST`::
+if tests are build download googletest from github (default: `ON`)
+when this option is set to `OFF` googletest binary package is a prerequisite for SEXP tests
+
+`WITH_SEXP_CLI:BOOL`::
+build the `sexp` client application (default: `ON`)
+
+`WITH_SANITIZERS:BOOL`::
+build with address and other sanitizers (default: `OFF`)
+(requires clang compiler)
+
+
+
+== SEXP command-line utility
+
+The `sexp` command-line utility is reference parser and generator of S-expressions.
+It can read, parse and print out SEXP in all defined formats.
+
+=== sexp switches:
+[options="header"]
+|=======================================================================================================
+| Switch | Description | Default
+3+| Input
+| -i <filename> | input file name | read input from console (stdin)
+| -p | prompt input if reading from console | disabled
+| -s | treat input as a single SEXP string | disabled, input is treated as S-expression
+3+| Output
+| -o <filename> | output file name: | write output to console (stdout)
+| -a | generate advanced transport format | enabled if no format is specified
+| -b | generate base-64 transport format | disabled
+| -c | generate canonical format | disabled
+| -l | suppress linefeeds after output | disabled
+| -w <width> | set output line width (0 implies no constraint)| 75
+3+| Miscellaneous
+| -x | execute repeatedly until EOF | process single S-expression then exit
+| -h | print help message and exit |
+|=======================================================================================================
+
+Running without switches implies: -p -a -b -c -x
+
+=== Usage examples:
+Prompt for S-expressions input from console, parse and output it to `certificate.dat` in base64 transport format
+[source]
+----
+sexp -o certificate.dat -p -b
+
+> Input:
+> (aa bb (cc dd))
+>
+> Writing base64 (of canonical) output to 'certificate.dat'
+----
+
+Parse all S-expressions from `certificate.dat`, output them to console in advanced transport format with no prompts
+[source]
+----
+sexp -i certificate.dat -x
+
+> (2:aa2:bb(2:cc2:dd))
+----
+
+Parse S-expressions from `certificate.dat`, output it to console in canonical, base64 and advanced format with prompts and no width limitation
+[source]
+----
+sexp -i certificate.dat -a -b -c -p -w 0
+
+> Reading input from certificate.dat
+>
+> Canonical output:
+> (2:aa2:bb(2:cc2:dd))
+> Base64 (of canonical) output:
+> {KDI6YWEyOmJiKDI6Y2MyOmRkKSk=}
+> Advanced transport output:
+> (aa bb (cc dd))
+----
+
+Repeatedly prompt for S-expressions input from console, parse and output it console in advanced, base64 and canonical formats
+[source]
+----
+sexp -p -a -b -c -x
+----
+or just
+----
+sexp
+
+> Input:
+> (abc def (ghi jkl))
+>
+> Canonical output:
+> (3:abc3:def(3:ghi3:jkl))
+> Base64 (of canonical) output:
+> {KDM6YWJjMzpkZWYoMzpnaGkzOmprbCkp}
+> Advanced transport output:
+> (abc def (ghi jkl))
+>
+> Input:
+> ^C
+----
+
+== License
+
+The code is made available as open-source software under the MIT License.
diff --git a/comm/third_party/rnp/src/libsexp/include/sexp/ext-key-format.h b/comm/third_party/rnp/src/libsexp/include/sexp/ext-key-format.h
new file mode 100644
index 0000000000..fc031a3473
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/include/sexp/ext-key-format.h
@@ -0,0 +1,99 @@
+/**
+ *
+ * Copyright (c) 2022, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <map>
+#include "sexp.h"
+
+namespace ext_key_format {
+
+void ext_key_error(
+ sexp::sexp_exception_t::severity level, const char *msg, size_t c1, size_t c2, int pos);
+
+class ext_key_input_stream_t;
+
+class extended_private_key_t {
+ public:
+ // Comparison of names is done case insensitively !!!
+ struct ci_less {
+ // case-independent (ci) compare_less binary function
+ bool operator()(const std::string &s1, const std::string &s2) const
+ {
+ return std::lexicographical_compare(
+ s1.begin(), s1.end(), s2.begin(), s2.end(), [](char a, char b) {
+ return std::tolower(a) < std::tolower(b);
+ });
+ }
+ };
+
+ // C++ 11 compatible version (no std::equals)
+ static bool iequals(const std::string &a, const std::string &b)
+ {
+ size_t sz = a.size();
+ if (b.size() != sz)
+ return false;
+ for (size_t i = 0; i < sz; ++i)
+ if (tolower(a[i]) != tolower(b[i]))
+ return false;
+ return true;
+ }
+
+ typedef std::multimap<std::string, std::string, ci_less> fields_map_t;
+
+ sexp::sexp_list_t key;
+ fields_map_t fields;
+
+ void parse(ext_key_input_stream_t &is);
+};
+
+class ext_key_input_stream_t : public sexp::sexp_input_stream_t {
+ private:
+ static const bool namechar[256]; /* true if allowed in the name field */
+
+ static bool is_newline_char(int c) { return c == '\r' || c == '\n'; };
+ static bool is_namechar(int c) { return ((c >= 0 && c <= 255) && namechar[c]); }
+
+ bool is_scanning_value;
+ bool has_key;
+
+ int skip_line(void);
+ virtual int read_char(void);
+ std::string scan_name(int c);
+ std::string scan_value(void);
+
+ public:
+ ext_key_input_stream_t(std::istream *i, size_t md = 0)
+ : sexp_input_stream_t(i, md), is_scanning_value(false), has_key(false)
+ {
+ }
+ virtual ~ext_key_input_stream_t() = default;
+ void scan(extended_private_key_t &extended_key);
+};
+} // namespace ext_key_format
diff --git a/comm/third_party/rnp/src/libsexp/include/sexp/sexp-error.h b/comm/third_party/rnp/src/libsexp/include/sexp/sexp-error.h
new file mode 100644
index 0000000000..332a63bcad
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/include/sexp/sexp-error.h
@@ -0,0 +1,77 @@
+/**
+ *
+ * Copyright (c) 2022, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <exception>
+#include <iostream>
+#include <string>
+
+namespace sexp {
+
+class sexp_exception_t : public std::exception {
+ public:
+ enum severity { error = 0, warning = 1 };
+
+ protected:
+ static severity verbosity;
+ static bool interactive;
+
+ int position; // May be EOF aka -1
+ severity level;
+ std::string message;
+
+ public:
+ sexp_exception_t(std::string error_message,
+ severity error_level,
+ int error_position,
+ const char *prefix = "SEXP")
+ : position{error_position}, level{error_level},
+ message{format(prefix, error_message, error_level, error_position)} {};
+
+ static std::string format(std::string prf,
+ std::string message,
+ severity level,
+ int position);
+
+ static bool shall_throw(severity level) { return level == error || verbosity != error; };
+ virtual const char *what(void) const throw() { return message.c_str(); };
+ severity get_level(void) const { return level; };
+ uint32_t get_position(void) const { return position; };
+ static severity get_verbosity(void) { return verbosity; };
+ static bool is_interactive(void) { return interactive; };
+ static void set_verbosity(severity new_verbosity) { verbosity = new_verbosity; };
+ static void set_interactive(bool new_interactive) { interactive = new_interactive; };
+};
+
+void sexp_error(
+ sexp_exception_t::severity level, const char *msg, size_t c1, size_t c2, int pos);
+
+} // namespace sexp
diff --git a/comm/third_party/rnp/src/libsexp/include/sexp/sexp.h b/comm/third_party/rnp/src/libsexp/include/sexp/sexp.h
new file mode 100644
index 0000000000..52cad55751
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/include/sexp/sexp.h
@@ -0,0 +1,435 @@
+/**
+ *
+ * Copyright (c) 2022-2023, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP standard header file: sexp.h
+ * Ronald L. Rivest
+ * 6/29/1997
+ */
+
+#pragma once
+
+#include <climits>
+#include <limits>
+#include <cctype>
+#include <locale>
+#include <cstring>
+#include <memory>
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cassert>
+
+#include "sexp-error.h"
+
+namespace sexp {
+/*
+ * SEXP octet_t definitions
+ * We maintain some presumable redundancy with ctype
+ * However, we do enforce 'C' locale this way
+ */
+
+class sexp_char_defs_t {
+ protected:
+ static const bool base64digit[256]; /* true if c is base64 digit */
+ static const bool tokenchar[256]; /* true if c can be in a token */
+ static const unsigned char values[256][3]; /* values of c as { dec. hex, base64 } digit */
+ static std::locale c_locale;
+
+ static bool is_white_space(int c)
+ {
+ return c >= 0 && c <= 255 && std::isspace((char) c, c_locale);
+ };
+ static bool is_dec_digit(int c)
+ {
+ return c >= 0 && c <= 255 && std::isdigit((char) c, c_locale);
+ };
+ static bool is_hex_digit(int c)
+ {
+ return c >= 0 && c <= 255 && std::isxdigit((char) c, c_locale);
+ };
+ static bool is_base64_digit(int c) { return c >= 0 && c <= 255 && base64digit[c]; };
+ static bool is_token_char(int c) { return c >= 0 && c <= 255 && tokenchar[c]; };
+ static bool is_alpha(int c)
+ {
+ return c >= 0 && c <= 255 && std::isalpha((char) c, c_locale);
+ };
+
+ /* decvalue(c) is value of c as dec digit */
+ static unsigned char decvalue(int c) { return (c >= 0 && c <= 255) ? values[c][0] : 0; };
+ /* hexvalue(c) is value of c as a hex digit */
+ static unsigned char hexvalue(int c) { return (c >= 0 && c <= 255) ? values[c][1] : 0; };
+ /* base64value(c) is value of c as base64 digit */
+ static unsigned char base64value(int c)
+ {
+ return (c >= 0 && c <= 255) ? values[c][2] : 0;
+ };
+};
+
+class sexp_string_t;
+class sexp_list_t;
+
+class sexp_output_stream_t;
+class sexp_input_stream_t;
+
+/*
+ * SEXP simple string
+ */
+
+typedef uint8_t octet_t;
+
+class sexp_simple_string_t : public std::basic_string<octet_t>, private sexp_char_defs_t {
+ public:
+ sexp_simple_string_t(void) = default;
+ sexp_simple_string_t(const octet_t *dt) : std::basic_string<octet_t>{dt} {}
+ sexp_simple_string_t(const octet_t *bt, size_t ln) : std::basic_string<octet_t>{bt, ln} {}
+ sexp_simple_string_t &append(int c)
+ {
+ (*this) += (octet_t)(c & 0xFF);
+ return *this;
+ }
+ // Returns length for printing simple string as a token
+ size_t advanced_length_token(void) const { return length(); }
+ // Returns length for printing simple string as a base64 string
+ size_t advanced_length_base64(void) const { return (2 + 4 * ((length() + 2) / 3)); }
+ // Returns length for printing simple string ss in quoted-string mode
+ size_t advanced_length_quoted(void) const { return (1 + length() + 1); }
+ // Returns length for printing simple string ss in hexadecimal mode
+ size_t advanced_length_hexadecimal(void) const { return (1 + 2 * length() + 1); }
+ size_t advanced_length(sexp_output_stream_t *os) const;
+
+ sexp_output_stream_t *print_canonical_verbatim(sexp_output_stream_t *os) const;
+ sexp_output_stream_t *print_advanced(sexp_output_stream_t *os) const;
+ sexp_output_stream_t *print_token(sexp_output_stream_t *os) const;
+ sexp_output_stream_t *print_quoted(sexp_output_stream_t *os) const;
+ sexp_output_stream_t *print_hexadecimal(sexp_output_stream_t *os) const;
+ sexp_output_stream_t *print_base64(sexp_output_stream_t *os) const;
+
+ bool can_print_as_quoted_string(void) const;
+ bool can_print_as_token(const sexp_output_stream_t *os) const;
+
+ bool operator==(const char *right) const noexcept
+ {
+ return length() == std::strlen(right) && std::memcmp(data(), right, length()) == 0;
+ }
+
+ bool operator!=(const char *right) const noexcept
+ {
+ return length() != std::strlen(right) || std::memcmp(data(), right, length()) != 0;
+ }
+
+ unsigned as_unsigned() const noexcept
+ {
+ return empty() ? std::numeric_limits<uint32_t>::max() :
+ (unsigned) atoi(reinterpret_cast<const char *>(c_str()));
+ }
+};
+
+inline bool operator==(const sexp_simple_string_t *left, const std::string &right) noexcept
+{
+ return *left == right.c_str();
+}
+
+inline bool operator!=(const sexp_simple_string_t *left, const std::string &right) noexcept
+{
+ return *left != right.c_str();
+}
+
+/*
+ * SEXP object
+ */
+
+class sexp_object_t {
+ public:
+ virtual ~sexp_object_t(){};
+
+ virtual sexp_output_stream_t *print_canonical(sexp_output_stream_t *os) const = 0;
+ virtual sexp_output_stream_t *print_advanced(sexp_output_stream_t *os) const;
+ virtual size_t advanced_length(sexp_output_stream_t *os) const = 0;
+
+ virtual sexp_list_t * sexp_list_view(void) noexcept { return nullptr; }
+ virtual sexp_string_t *sexp_string_view(void) noexcept { return nullptr; }
+ virtual bool is_sexp_list(void) const noexcept { return false; }
+ virtual bool is_sexp_string(void) const noexcept { return false; }
+
+ virtual const sexp_list_t *sexp_list_at(
+ std::vector<std::shared_ptr<sexp_object_t>>::size_type pos) const noexcept
+ {
+ return nullptr;
+ }
+ virtual const sexp_string_t *sexp_string_at(
+ std::vector<std::shared_ptr<sexp_object_t>>::size_type pos) const noexcept
+ {
+ return nullptr;
+ }
+ virtual const sexp_simple_string_t *sexp_simple_string_at(
+ std::vector<std::shared_ptr<sexp_object_t>>::size_type pos) const noexcept
+ {
+ return nullptr;
+ }
+ virtual bool operator==(const char *right) const noexcept { return false; }
+ virtual bool operator!=(const char *right) const noexcept { return true; }
+ virtual unsigned as_unsigned() const noexcept
+ {
+ return std::numeric_limits<uint32_t>::max();
+ }
+};
+
+/*
+ * SEXP string
+ */
+
+class sexp_string_t : public sexp_object_t {
+ protected:
+ bool with_presentation_hint;
+ sexp_simple_string_t presentation_hint;
+ sexp_simple_string_t data_string;
+
+ public:
+ sexp_string_t(const octet_t *dt) : with_presentation_hint(false), data_string(dt) {}
+ sexp_string_t(const octet_t *bt, size_t ln)
+ : with_presentation_hint(false), data_string(bt, ln)
+ {
+ }
+ sexp_string_t(const std::string &str)
+ : with_presentation_hint(false),
+ data_string(reinterpret_cast<const octet_t *>(str.data()))
+ {
+ }
+ sexp_string_t(void) : with_presentation_hint(false) {}
+ sexp_string_t(sexp_input_stream_t *sis) { parse(sis); };
+
+ const bool has_presentation_hint(void) const noexcept { return with_presentation_hint; }
+ const sexp_simple_string_t &get_string(void) const noexcept { return data_string; }
+ const sexp_simple_string_t &set_string(const sexp_simple_string_t &ss)
+ {
+ return data_string = ss;
+ }
+ const sexp_simple_string_t &get_presentation_hint(void) const noexcept
+ {
+ return presentation_hint;
+ }
+ const sexp_simple_string_t &set_presentation_hint(const sexp_simple_string_t &ph)
+ {
+ with_presentation_hint = true;
+ return presentation_hint = ph;
+ }
+
+ virtual sexp_output_stream_t *print_canonical(sexp_output_stream_t *os) const;
+ virtual sexp_output_stream_t *print_advanced(sexp_output_stream_t *os) const;
+ virtual size_t advanced_length(sexp_output_stream_t *os) const;
+
+ virtual sexp_string_t *sexp_string_view(void) noexcept { return this; }
+ virtual bool is_sexp_string(void) const noexcept { return true; }
+
+ virtual bool operator==(const char *right) const noexcept { return data_string == right; }
+ virtual bool operator!=(const char *right) const noexcept { return data_string != right; }
+
+ void parse(sexp_input_stream_t *sis);
+ virtual unsigned as_unsigned() const noexcept { return data_string.as_unsigned(); }
+};
+
+inline bool operator==(const sexp_string_t *left, const std::string &right) noexcept
+{
+ return *left == right.c_str();
+}
+
+inline bool operator!=(const sexp_string_t *left, const std::string &right) noexcept
+{
+ return *left != right.c_str();
+}
+
+/*
+ * SEXP list
+ */
+
+class sexp_list_t : public sexp_object_t, public std::vector<std::shared_ptr<sexp_object_t>> {
+ public:
+ virtual ~sexp_list_t() {}
+
+ virtual sexp_output_stream_t *print_canonical(sexp_output_stream_t *os) const;
+ virtual sexp_output_stream_t *print_advanced(sexp_output_stream_t *os) const;
+ virtual size_t advanced_length(sexp_output_stream_t *os) const;
+
+ virtual sexp_list_t *sexp_list_view(void) noexcept { return this; }
+ virtual bool is_sexp_list(void) const noexcept { return true; }
+
+ virtual const sexp_list_t *sexp_list_at(size_type pos) const noexcept
+ {
+ return pos < size() ? (*at(pos)).sexp_list_view() : nullptr;
+ }
+ virtual const sexp_string_t *sexp_string_at(size_type pos) const noexcept
+ {
+ return pos < size() ? (*at(pos)).sexp_string_view() : nullptr;
+ }
+ const sexp_simple_string_t *sexp_simple_string_at(size_type pos) const noexcept
+ {
+ auto s = sexp_string_at(pos);
+ return s != nullptr ? &s->get_string() : nullptr;
+ }
+
+ void parse(sexp_input_stream_t *sis);
+};
+
+/*
+ * SEXP input stream
+ */
+
+class sexp_input_stream_t : public sexp_char_defs_t {
+ protected:
+ std::istream *input_file;
+ uint32_t byte_size; /* 4 or 6 or 8 == currently scanning mode */
+ int next_char; /* character currently being scanned */
+ uint32_t bits; /* Bits waiting to be used */
+ uint32_t n_bits; /* number of such bits waiting to be used */
+ int count; /* number of 8-bit characters output by get_char */
+ size_t depth; /* current depth of nested SEXP lists */
+ size_t max_depth; /* maximum allowed depth of nested SEXP lists, 0 if no limit */
+
+ virtual int read_char(void);
+
+ public:
+ sexp_input_stream_t(std::istream *i, size_t max_depth = 0);
+ virtual ~sexp_input_stream_t() = default;
+ sexp_input_stream_t *set_input(std::istream *i, size_t max_depth = 0);
+ sexp_input_stream_t *set_byte_size(uint32_t new_byte_size);
+ uint32_t get_byte_size(void) { return byte_size; }
+ sexp_input_stream_t *get_char(void);
+ sexp_input_stream_t *skip_white_space(void);
+ sexp_input_stream_t *skip_char(int c);
+ sexp_input_stream_t *increase_depth(void)
+ {
+ if (max_depth != 0 && ++depth > max_depth)
+ sexp_error(sexp_exception_t::error,
+ "Maximum allowed SEXP list depth (%u) is exceeded",
+ max_depth,
+ 0,
+ count);
+ return this;
+ }
+ sexp_input_stream_t *decrease_depth(void)
+ {
+ depth--;
+ return this;
+ }
+
+ std::shared_ptr<sexp_object_t> scan_to_eof();
+ std::shared_ptr<sexp_object_t> scan_object(void);
+ std::shared_ptr<sexp_string_t> scan_string(void);
+ std::shared_ptr<sexp_list_t> scan_list(void);
+ sexp_simple_string_t scan_simple_string(void);
+ void scan_token(sexp_simple_string_t &ss);
+ void scan_verbatim_string(sexp_simple_string_t &ss, uint32_t length);
+ void scan_quoted_string(sexp_simple_string_t &ss, uint32_t length);
+ void scan_hexadecimal_string(sexp_simple_string_t &ss, uint32_t length);
+ void scan_base64_string(sexp_simple_string_t &ss, uint32_t length);
+ uint32_t scan_decimal_string(void);
+
+ int get_next_char(void) const { return next_char; }
+ int set_next_char(int c) { return next_char = c; }
+};
+
+/*
+ * SEXP output stream
+ */
+
+class sexp_output_stream_t {
+ public:
+ const uint32_t default_line_length = 75;
+ enum sexp_print_mode { /* PRINTING MODES */
+ canonical = 1, /* standard for hashing and tranmission */
+ base64 = 2, /* base64 version of canonical */
+ advanced = 3 /* pretty-printed */
+ };
+
+ protected:
+ std::ostream * output_file;
+ uint32_t base64_count; /* number of hex or base64 chars printed this region */
+ uint32_t byte_size; /* 4 or 6 or 8 depending on output mode */
+ uint32_t bits; /* bits waiting to go out */
+ uint32_t n_bits; /* number of bits waiting to go out */
+ sexp_print_mode mode; /* base64, advanced, or canonical */
+ uint32_t column; /* column where next character will go */
+ uint32_t max_column; /* max usable column, or 0 if no maximum */
+ uint32_t indent; /* current indentation level (starts at 0) */
+ public:
+ sexp_output_stream_t(std::ostream *o);
+ sexp_output_stream_t *set_output(std::ostream *o);
+ sexp_output_stream_t *put_char(int c); /* output a character */
+ sexp_output_stream_t *new_line(sexp_print_mode mode); /* go to next line (and indent) */
+ sexp_output_stream_t *var_put_char(int c);
+ sexp_output_stream_t *flush(void);
+ sexp_output_stream_t *print_decimal(uint64_t n);
+
+ sexp_output_stream_t *change_output_byte_size(int newByteSize, sexp_print_mode mode);
+
+ sexp_output_stream_t *print_canonical(const std::shared_ptr<sexp_object_t> &obj)
+ {
+ return obj->print_canonical(this);
+ }
+ sexp_output_stream_t *print_advanced(const std::shared_ptr<sexp_object_t> &obj)
+ {
+ return obj->print_advanced(this);
+ };
+ sexp_output_stream_t *print_base64(const std::shared_ptr<sexp_object_t> &obj);
+ sexp_output_stream_t *print_canonical(const sexp_simple_string_t *ss)
+ {
+ return ss->print_canonical_verbatim(this);
+ }
+ sexp_output_stream_t *print_advanced(const sexp_simple_string_t *ss)
+ {
+ return ss->print_advanced(this);
+ };
+
+ uint32_t get_byte_size(void) const { return byte_size; }
+ uint32_t get_column(void) const { return column; }
+ sexp_output_stream_t *reset_column(void)
+ {
+ column = 0;
+ return this;
+ }
+ uint32_t get_max_column(void) const { return max_column; }
+ sexp_output_stream_t *set_max_column(uint32_t mc)
+ {
+ max_column = mc;
+ return this;
+ }
+ sexp_output_stream_t *inc_indent(void)
+ {
+ ++indent;
+ return this;
+ }
+ sexp_output_stream_t *dec_indent(void)
+ {
+ --indent;
+ return this;
+ }
+};
+
+} // namespace sexp
diff --git a/comm/third_party/rnp/src/libsexp/src/ext-key-format.cpp b/comm/third_party/rnp/src/libsexp/src/ext-key-format.cpp
new file mode 100644
index 0000000000..a0c0d04b73
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/ext-key-format.cpp
@@ -0,0 +1,314 @@
+/**
+ *
+ * Copyright (c) 2022, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sexp/ext-key-format.h>
+
+using namespace sexp;
+
+namespace ext_key_format {
+
+void ext_key_error(
+ sexp_exception_t::severity level, const char *msg, size_t c1, size_t c2, int pos)
+{
+ char tmp[256];
+ sexp_exception_t::severity l = (sexp_exception_t::severity) level;
+ snprintf(tmp, sizeof(tmp) / sizeof(tmp[0]), msg, c1, c2);
+ if (sexp_exception_t::shall_throw(l))
+ throw sexp_exception_t(tmp, l, pos, "EXTENDED KEY FORMAT");
+ if (sexp_exception_t::is_interactive()) {
+ std::cout.flush() << std::endl
+ << "*** "
+ << sexp_exception_t::format("EXTENDED KEY FORMAT", tmp, l, pos)
+ << " ***" << std::endl;
+ }
+}
+
+// Valid characters are all ASCII letters, numbers and the hyphen.
+// true if allowed in the name field
+const bool ext_key_input_stream_t::namechar[256] = {
+ /* 0x00 */ false, /* 0x01 */ false, /* 0x02 */ false,
+ /* 0x03 */ false, /* 0x04 */ false, /* 0x05 */ false,
+ /* 0x06 */ false, /* 0x07 */ false, /* 0x08 */ false,
+ /* 0x09 */ false, /* 0x0a */ false, /* 0x0b */ false,
+ /* 0x0c */ false, /* 0x0d */ false, /* 0x0e */ false,
+ /* 0x0f */ false, /* 0x10 */ false, /* 0x11 */ false,
+ /* 0x12 */ false, /* 0x13 */ false, /* 0x14 */ false,
+ /* 0x15 */ false, /* 0x16 */ false, /* 0x17 */ false,
+ /* 0x18 */ false, /* 0x19 */ false, /* 0x1a */ false,
+ /* 0x1b */ false, /* 0x1c */ false, /* 0x1d */ false,
+ /* 0x1e */ false, /* 0x1f */ false, /* 0x20 */ false,
+ /* 0x21 ! */ false, /* 0x22 " */ false, /* 0x23 # */ false,
+ /* 0x24 $ */ false, /* 0x25 % */ false, /* 0x26 & */ false,
+ /* 0x27 ' */ false, /* 0x28 ( */ false, /* 0x29 ) */ false,
+ /* 0x2a * */ false, /* 0x2b + */ false, /* 0x2c , */ false,
+ /* 0x2d - */ true, /* 0x2e . */ false, /* 0x2f / */ false,
+ /* 0x30 0 */ true, /* 0x31 1 */ true, /* 0x32 2 */ true,
+ /* 0x33 3 */ true, /* 0x34 4 */ true, /* 0x35 5 */ true,
+ /* 0x36 6 */ true, /* 0x37 7 */ true, /* 0x38 8 */ true,
+ /* 0x39 9 */ true, /* 0x3a : */ false, /* 0x3b ; */ false,
+ /* 0x3c < */ false, /* 0x3d = */ false, /* 0x3e > */ false,
+ /* 0x3f ? */ false, /* 0x40 @ */ false, /* 0x41 A */ true,
+ /* 0x42 B */ true, /* 0x43 C */ true, /* 0x44 D */ true,
+ /* 0x45 E */ true, /* 0x46 F */ true, /* 0x47 G */ true,
+ /* 0x48 H */ true, /* 0x49 I */ true, /* 0x4a J */ true,
+ /* 0x4b K */ true, /* 0x4c L */ true, /* 0x4d M */ true,
+ /* 0x4e N */ true, /* 0x4f O */ true, /* 0x50 P */ true,
+ /* 0x51 Q */ true, /* 0x52 R */ true, /* 0x53 S */ true,
+ /* 0x54 T */ true, /* 0x55 U */ true, /* 0x56 V */ true,
+ /* 0x57 W */ true, /* 0x58 X */ true, /* 0x59 Y */ true,
+ /* 0x5a Z */ true, /* 0x5b [ */ false, /* 0x5c \ */ false,
+ /* 0x5d ] */ false, /* 0x5e ^ */ false, /* 0x5f _ */ false,
+ /* 0x60 ` */ false, /* 0x61 a */ true, /* 0x62 b */ true,
+ /* 0x63 c */ true, /* 0x64 d */ true, /* 0x65 e */ true,
+ /* 0x66 f */ true, /* 0x67 g */ true, /* 0x68 h */ true,
+ /* 0x69 i */ true, /* 0x6a j */ true, /* 0x6b k */ true,
+ /* 0x6c l */ true, /* 0x6d m */ true, /* 0x6e n */ true,
+ /* 0x6f o */ true, /* 0x70 p */ true, /* 0x71 q */ true,
+ /* 0x72 r */ true, /* 0x73 s */ true, /* 0x74 t */ true,
+ /* 0x75 u */ true, /* 0x76 v */ true, /* 0x77 w */ true,
+ /* 0x78 x */ true, /* 0x79 y */ true, /* 0x7a z */ true,
+ /* 0x7b { */ false, /* 0x7c | */ false, /* 0x7d } */ false,
+ /* 0x7e ~ */ false, /* 0x7f */ false, /* 0x80 */ false,
+ /* 0x81 */ false, /* 0x82 */ false, /* 0x83 */ false,
+ /* 0x84 */ false, /* 0x85 */ false, /* 0x86 */ false,
+ /* 0x87 */ false, /* 0x88 */ false, /* 0x89 */ false,
+ /* 0x8a */ false, /* 0x8b */ false, /* 0x8c */ false,
+ /* 0x8d */ false, /* 0x8e */ false, /* 0x8f */ false,
+ /* 0x90 */ false, /* 0x91 */ false, /* 0x92 */ false,
+ /* 0x93 */ false, /* 0x94 */ false, /* 0x95 */ false,
+ /* 0x96 */ false, /* 0x97 */ false, /* 0x98 */ false,
+ /* 0x99 */ false, /* 0x9a */ false, /* 0x9b */ false,
+ /* 0x9c */ false, /* 0x9d */ false, /* 0x9e */ false,
+ /* 0x9f */ false, /* 0xa0 */ false, /* 0xa1 */ false,
+ /* 0xa2 */ false, /* 0xa3 */ false, /* 0xa4 */ false,
+ /* 0xa5 */ false, /* 0xa6 */ false, /* 0xa7 */ false,
+ /* 0xa8 */ false, /* 0xa9 */ false, /* 0xaa */ false,
+ /* 0xab */ false, /* 0xac */ false, /* 0xad */ false,
+ /* 0xae */ false, /* 0xaf */ false, /* 0xb0 */ false,
+ /* 0xb1 */ false, /* 0xb2 */ false, /* 0xb3 */ false,
+ /* 0xb4 */ false, /* 0xb5 */ false, /* 0xb6 */ false,
+ /* 0xb7 */ false, /* 0xb8 */ false, /* 0xb9 */ false,
+ /* 0xba */ false, /* 0xbb */ false, /* 0xbc */ false,
+ /* 0xbd */ false, /* 0xbe */ false, /* 0xbf */ false,
+ /* 0xc0 */ false, /* 0xc1 */ false, /* 0xc2 */ false,
+ /* 0xc3 */ false, /* 0xc4 */ false, /* 0xc5 */ false,
+ /* 0xc6 */ false, /* 0xc7 */ false, /* 0xc8 */ false,
+ /* 0xc9 */ false, /* 0xca */ false, /* 0xcb */ false,
+ /* 0xcc */ false, /* 0xcd */ false, /* 0xce */ false,
+ /* 0xcf */ false, /* 0xd0 */ false, /* 0xd1 */ false,
+ /* 0xd2 */ false, /* 0xd3 */ false, /* 0xd4 */ false,
+ /* 0xd5 */ false, /* 0xd6 */ false, /* 0xd7 */ false,
+ /* 0xd8 */ false, /* 0xd9 */ false, /* 0xda */ false,
+ /* 0xdb */ false, /* 0xdc */ false, /* 0xdd */ false,
+ /* 0xde */ false, /* 0xdf */ false, /* 0xe0 */ false,
+ /* 0xe1 */ false, /* 0xe2 */ false, /* 0xe3 */ false,
+ /* 0xe4 */ false, /* 0xe5 */ false, /* 0xe6 */ false,
+ /* 0xe7 */ false, /* 0xe8 */ false, /* 0xe9 */ false,
+ /* 0xea */ false, /* 0xeb */ false, /* 0xec */ false,
+ /* 0xed */ false, /* 0xee */ false, /* 0xef */ false,
+ /* 0xf0 */ false, /* 0xf1 */ false, /* 0xf2 */ false,
+ /* 0xf3 */ false, /* 0xf4 */ false, /* 0xf5 */ false,
+ /* 0xf6 */ false, /* 0xf7 */ false, /* 0xf8 */ false,
+ /* 0xf9 */ false, /* 0xfa */ false, /* 0xfb */ false,
+ /* 0xfc */ false, /* 0xfd */ false, /* 0xfe */ false};
+
+/*
+ * ext_key_input_stream_t::skip_line
+ */
+int ext_key_input_stream_t::skip_line(void)
+{
+ int c;
+ do {
+ c = input_file->get();
+ } while (!is_newline_char(c) && c != EOF);
+ return c;
+}
+
+/*
+ * ext_key_input_stream_t::read_char
+ */
+int ext_key_input_stream_t::read_char(void)
+{
+ int lookahead_1 = input_file->get();
+ count++;
+ if (is_scanning_value && is_newline_char(lookahead_1)) {
+ while (true) {
+ int lookahead_2 = input_file->peek();
+ if (lookahead_1 == '\r' && lookahead_2 == '\n') {
+ lookahead_1 = input_file->get();
+ count++;
+ lookahead_2 = input_file->peek();
+ }
+ if (lookahead_2 == ' ') {
+ input_file->get();
+ count++;
+ lookahead_2 = input_file->peek();
+ if (lookahead_2 == '#') {
+ lookahead_1 = skip_line();
+ continue;
+ }
+ if (is_newline_char(lookahead_2)) {
+ lookahead_1 = lookahead_2;
+ continue;
+ }
+ lookahead_1 = input_file->get();
+ count++;
+ }
+ return lookahead_1;
+ }
+ }
+ return lookahead_1;
+}
+
+/*
+ * ext_key_input_stream_t::scan_name
+ * A name must start with a letter and end with a colon. Valid characters are all ASCII
+ * letters, numbers and the hyphen. Comparison of names is done case insensitively. Names may
+ * be used several times to represent an array of values. Note that the name “Key” is special
+ * in that it is madandory must occur only once.
+ */
+
+std::string ext_key_input_stream_t::scan_name(int c)
+{
+ std::string name;
+ if (!is_alpha(c)) {
+ ext_key_error(sexp_exception_t::error,
+ isprint(next_char) ?
+ "unexpected character '%c' (0x%x) found starting a name field" :
+ "unexpected character '0x%x' found starting a name field",
+ c,
+ c,
+ count);
+ } else {
+ name += (char) c;
+ c = read_char();
+ while (c != ':') {
+ if (c == EOF) {
+ ext_key_error(sexp_exception_t::error, "unexpected end of file", 0, 0, count);
+ }
+ if (is_newline_char(c)) {
+ ext_key_error(sexp_exception_t::error, "unexpected end of line", 0, 0, count);
+ }
+ if (!is_namechar(c)) {
+ ext_key_error(sexp_exception_t::error,
+ isprint(next_char) ?
+ "unexpected character '%c' (0x%x) found in a name field" :
+ "unexpected character '0x%x' found in a name field",
+ c,
+ c,
+ count);
+ }
+ name += (int) c;
+ c = read_char();
+ }
+ }
+ return name;
+}
+
+/*
+ * ext_key_input_stream_t::scan_value
+ * Values are UTF-8 encoded strings. Values can be wrapped at any point, and continued in
+ * the next line indicated by leading whitespace. A continuation line with one leading space
+ * does not introduce a blank so that the lines can be effectively concatenated. A blank
+ * line as part of a continuation line encodes a newline.
+ */
+std::string ext_key_input_stream_t::scan_value(void)
+{
+ std::string value;
+ int c;
+ do {
+ c = read_char();
+ } while (is_white_space(c));
+ while (c != EOF && !is_newline_char(c)) {
+ value += c;
+ c = read_char();
+ }
+ return value;
+}
+
+/*
+ * ext_key_input_stream_t::scan
+ * GnuPG 2.3+ uses a new format to store private keys that is both more flexible and easier to
+ * read and edit by human beings. The new format stores name, value-pairs using the common mail
+ * and http header convention.
+ */
+void ext_key_input_stream_t::scan(extended_private_key_t &res)
+{
+ set_byte_size(8);
+ int c = read_char();
+ if (c == '(') {
+ set_next_char(c);
+ res.key.parse(this);
+ has_key = true;
+ } else {
+ while (c != EOF) {
+ // Comparison of names is done case insensitively
+ std::string name = scan_name(c);
+ // The name “Key” is special in that it is mandatory and must occur only once.
+ // The associated value holds the actual S-expression with the cryptographic key.
+ // The S-expression is formatted using the ‘Advanced Format’
+ // (GCRYSEXP_FMT_ADVANCED) that avoids non-printable characters so that the file
+ // can be easily inspected and edited.
+ is_scanning_value = true;
+ if (extended_private_key_t::iequals(name, "key")) {
+ if (has_key) {
+ ext_key_error(sexp_exception_t::error,
+ "'key' field must occur only once",
+ 0,
+ 0,
+ count);
+ }
+ do {
+ c = read_char();
+ } while (is_white_space(c));
+ set_next_char(c);
+ res.key.parse(this);
+ has_key = true;
+ } else {
+ std::string value = scan_value();
+ res.fields.insert(std::pair<std::string, std::string>{name, value});
+ }
+ c = read_char();
+ is_scanning_value = false;
+ }
+ }
+ if (!has_key) {
+ ext_key_error(sexp_exception_t::error, "missing mandatory 'key' field", 0, 0, count);
+ }
+}
+
+/*
+ * extended_private_key_t::parse
+ */
+void extended_private_key_t::parse(ext_key_input_stream_t &is)
+{
+ is.scan(*this);
+}
+
+} // namespace ext_key_format \ No newline at end of file
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-char-defs.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-char-defs.cpp
new file mode 100644
index 0000000000..8a727d5737
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-char-defs.cpp
@@ -0,0 +1,351 @@
+/**
+ *
+ * Copyright (c) 2022, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP implementation code sexp-input.c
+ * Ron Rivest
+ * 7/21/1997
+ */
+
+#include <sexp/sexp.h>
+
+namespace sexp {
+
+/**************************************/
+/* CHARACTER ROUTINES AND DEFINITIONS */
+/**************************************/
+std::locale sexp_char_defs_t::c_locale{"C"};
+
+const unsigned char sexp_char_defs_t::values[256][3] =
+ {/* values of c as { dec. hex, base64 } digit */
+ {/* 0x00 */ 0x00, 0x00, 0x00}, {/* 0x01 */ 0x00, 0x00, 0x00},
+ {/* 0x02 */ 0x00, 0x00, 0x00}, {/* 0x03 */ 0x00, 0x00, 0x00},
+ {/* 0x04 */ 0x00, 0x00, 0x00}, {/* 0x05 */ 0x00, 0x00, 0x00},
+ {/* 0x06 */ 0x00, 0x00, 0x00}, {/* 0x07 */ 0x00, 0x00, 0x00},
+ {/* 0x08 */ 0x00, 0x00, 0x00}, {/* 0x09 */ 0x00, 0x00, 0x00},
+ {/* 0x0a */ 0x00, 0x00, 0x00}, {/* 0x0b */ 0x00, 0x00, 0x00},
+ {/* 0x0c */ 0x00, 0x00, 0x00}, {/* 0x0d */ 0x00, 0x00, 0x00},
+ {/* 0x0e */ 0x00, 0x00, 0x00}, {/* 0x0f */ 0x00, 0x00, 0x00},
+ {/* 0x10 */ 0x00, 0x00, 0x00}, {/* 0x11 */ 0x00, 0x00, 0x00},
+ {/* 0x12 */ 0x00, 0x00, 0x00}, {/* 0x13 */ 0x00, 0x00, 0x00},
+ {/* 0x14 */ 0x00, 0x00, 0x00}, {/* 0x15 */ 0x00, 0x00, 0x00},
+ {/* 0x16 */ 0x00, 0x00, 0x00}, {/* 0x17 */ 0x00, 0x00, 0x00},
+ {/* 0x18 */ 0x00, 0x00, 0x00}, {/* 0x19 */ 0x00, 0x00, 0x00},
+ {/* 0x1a */ 0x00, 0x00, 0x00}, {/* 0x1b */ 0x00, 0x00, 0x00},
+ {/* 0x1c */ 0x00, 0x00, 0x00}, {/* 0x1d */ 0x00, 0x00, 0x00},
+ {/* 0x1e */ 0x00, 0x00, 0x00}, {/* 0x1f */ 0x00, 0x00, 0x00},
+ {/* 0x20 */ 0x00, 0x00, 0x00}, {/* 0x21 ! */ 0x00, 0x00, 0x00},
+ {/* 0x22 " */ 0x00, 0x00, 0x00}, {/* 0x23 # */ 0x00, 0x00, 0x00},
+ {/* 0x24 $ */ 0x00, 0x00, 0x00}, {/* 0x25 % */ 0x00, 0x00, 0x00},
+ {/* 0x26 & */ 0x00, 0x00, 0x00}, {/* 0x27 ' */ 0x00, 0x00, 0x00},
+ {/* 0x28 ( */ 0x00, 0x00, 0x00}, {/* 0x29 ) */ 0x00, 0x00, 0x00},
+ {/* 0x2a * */ 0x00, 0x00, 0x00}, {/* 0x2b + */ 0x00, 0x00, 0x3e},
+ {/* 0x2c , */ 0x00, 0x00, 0x00}, {/* 0x2d - */ 0x00, 0x00, 0x00},
+ {/* 0x2e . */ 0x00, 0x00, 0x00}, {/* 0x2f / */ 0x00, 0x00, 0x3f},
+ {/* 0x30 0 */ 0x00, 0x00, 0x34}, {/* 0x31 1 */ 0x01, 0x01, 0x35},
+ {/* 0x32 2 */ 0x02, 0x02, 0x36}, {/* 0x33 3 */ 0x03, 0x03, 0x37},
+ {/* 0x34 4 */ 0x04, 0x04, 0x38}, {/* 0x35 5 */ 0x05, 0x05, 0x39},
+ {/* 0x36 6 */ 0x06, 0x06, 0x3a}, {/* 0x37 7 */ 0x07, 0x07, 0x3b},
+ {/* 0x38 8 */ 0x08, 0x08, 0x3c}, {/* 0x39 9 */ 0x09, 0x09, 0x3d},
+ {/* 0x3a : */ 0x00, 0x00, 0x00}, {/* 0x3b ; */ 0x00, 0x00, 0x00},
+ {/* 0x3c < */ 0x00, 0x00, 0x00}, {/* 0x3d = */ 0x00, 0x00, 0x00},
+ {/* 0x3e > */ 0x00, 0x00, 0x00}, {/* 0x3f ? */ 0x00, 0x00, 0x00},
+ {/* 0x40 @ */ 0x00, 0x00, 0x00}, {/* 0x41 A */ 0x00, 0x0a, 0x00},
+ {/* 0x42 B */ 0x00, 0x0b, 0x01}, {/* 0x43 C */ 0x00, 0x0c, 0x02},
+ {/* 0x44 D */ 0x00, 0x0d, 0x03}, {/* 0x45 E */ 0x00, 0x0e, 0x04},
+ {/* 0x46 F */ 0x00, 0x0f, 0x05}, {/* 0x47 G */ 0x00, 0x00, 0x06},
+ {/* 0x48 H */ 0x00, 0x00, 0x07}, {/* 0x49 I */ 0x00, 0x00, 0x08},
+ {/* 0x4a J */ 0x00, 0x00, 0x09}, {/* 0x4b K */ 0x00, 0x00, 0x0a},
+ {/* 0x4c L */ 0x00, 0x00, 0x0b}, {/* 0x4d M */ 0x00, 0x00, 0x0c},
+ {/* 0x4e N */ 0x00, 0x00, 0x0d}, {/* 0x4f O */ 0x00, 0x00, 0x0e},
+ {/* 0x50 P */ 0x00, 0x00, 0x0f}, {/* 0x51 Q */ 0x00, 0x00, 0x10},
+ {/* 0x52 R */ 0x00, 0x00, 0x11}, {/* 0x53 S */ 0x00, 0x00, 0x12},
+ {/* 0x54 T */ 0x00, 0x00, 0x13}, {/* 0x55 U */ 0x00, 0x00, 0x14},
+ {/* 0x56 V */ 0x00, 0x00, 0x15}, {/* 0x57 W */ 0x00, 0x00, 0x16},
+ {/* 0x58 X */ 0x00, 0x00, 0x17}, {/* 0x59 Y */ 0x00, 0x00, 0x18},
+ {/* 0x5a Z */ 0x00, 0x00, 0x19}, {/* 0x5b [ */ 0x00, 0x00, 0x00},
+ {/* 0x5c \ */ 0x00, 0x00, 0x00}, {/* 0x5d ] */ 0x00, 0x00, 0x00},
+ {/* 0x5e ^ */ 0x00, 0x00, 0x00}, {/* 0x5f _ */ 0x00, 0x00, 0x00},
+ {/* 0x60 ` */ 0x00, 0x00, 0x00}, {/* 0x61 a */ 0x00, 0x0a, 0x1a},
+ {/* 0x62 b */ 0x00, 0x0b, 0x1b}, {/* 0x63 c */ 0x00, 0x0c, 0x1c},
+ {/* 0x64 d */ 0x00, 0x0d, 0x1d}, {/* 0x65 e */ 0x00, 0x0e, 0x1e},
+ {/* 0x66 f */ 0x00, 0x0f, 0x1f}, {/* 0x67 g */ 0x00, 0x00, 0x20},
+ {/* 0x68 h */ 0x00, 0x00, 0x21}, {/* 0x69 i */ 0x00, 0x00, 0x22},
+ {/* 0x6a j */ 0x00, 0x00, 0x23}, {/* 0x6b k */ 0x00, 0x00, 0x24},
+ {/* 0x6c l */ 0x00, 0x00, 0x25}, {/* 0x6d m */ 0x00, 0x00, 0x26},
+ {/* 0x6e n */ 0x00, 0x00, 0x27}, {/* 0x6f o */ 0x00, 0x00, 0x28},
+ {/* 0x70 p */ 0x00, 0x00, 0x29}, {/* 0x71 q */ 0x00, 0x00, 0x2a},
+ {/* 0x72 r */ 0x00, 0x00, 0x2b}, {/* 0x73 s */ 0x00, 0x00, 0x2c},
+ {/* 0x74 t */ 0x00, 0x00, 0x2d}, {/* 0x75 u */ 0x00, 0x00, 0x2e},
+ {/* 0x76 v */ 0x00, 0x00, 0x2f}, {/* 0x77 w */ 0x00, 0x00, 0x30},
+ {/* 0x78 x */ 0x00, 0x00, 0x31}, {/* 0x79 y */ 0x00, 0x00, 0x32},
+ {/* 0x7a z */ 0x00, 0x00, 0x33}, {/* 0x7b { */ 0x00, 0x00, 0x00},
+ {/* 0x7c | */ 0x00, 0x00, 0x00}, {/* 0x7d } */ 0x00, 0x00, 0x00},
+ {/* 0x7e ~ */ 0x00, 0x00, 0x00}, {/* 0x7f */ 0x00, 0x00, 0x00},
+ {/* 0x80 */ 0x00, 0x00, 0x00}, {/* 0x81 */ 0x00, 0x00, 0x00},
+ {/* 0x82 */ 0x00, 0x00, 0x00}, {/* 0x83 */ 0x00, 0x00, 0x00},
+ {/* 0x84 */ 0x00, 0x00, 0x00}, {/* 0x85 */ 0x00, 0x00, 0x00},
+ {/* 0x86 */ 0x00, 0x00, 0x00}, {/* 0x87 */ 0x00, 0x00, 0x00},
+ {/* 0x88 */ 0x00, 0x00, 0x00}, {/* 0x89 */ 0x00, 0x00, 0x00},
+ {/* 0x8a */ 0x00, 0x00, 0x00}, {/* 0x8b */ 0x00, 0x00, 0x00},
+ {/* 0x8c */ 0x00, 0x00, 0x00}, {/* 0x8d */ 0x00, 0x00, 0x00},
+ {/* 0x8e */ 0x00, 0x00, 0x00}, {/* 0x8f */ 0x00, 0x00, 0x00},
+ {/* 0x90 */ 0x00, 0x00, 0x00}, {/* 0x91 */ 0x00, 0x00, 0x00},
+ {/* 0x92 */ 0x00, 0x00, 0x00}, {/* 0x93 */ 0x00, 0x00, 0x00},
+ {/* 0x94 */ 0x00, 0x00, 0x00}, {/* 0x95 */ 0x00, 0x00, 0x00},
+ {/* 0x96 */ 0x00, 0x00, 0x00}, {/* 0x97 */ 0x00, 0x00, 0x00},
+ {/* 0x98 */ 0x00, 0x00, 0x00}, {/* 0x99 */ 0x00, 0x00, 0x00},
+ {/* 0x9a */ 0x00, 0x00, 0x00}, {/* 0x9b */ 0x00, 0x00, 0x00},
+ {/* 0x9c */ 0x00, 0x00, 0x00}, {/* 0x9d */ 0x00, 0x00, 0x00},
+ {/* 0x9e */ 0x00, 0x00, 0x00}, {/* 0x9f */ 0x00, 0x00, 0x00},
+ {/* 0xa0 */ 0x00, 0x00, 0x00}, {/* 0xa1 */ 0x00, 0x00, 0x00},
+ {/* 0xa2 */ 0x00, 0x00, 0x00}, {/* 0xa3 */ 0x00, 0x00, 0x00},
+ {/* 0xa4 */ 0x00, 0x00, 0x00}, {/* 0xa5 */ 0x00, 0x00, 0x00},
+ {/* 0xa6 */ 0x00, 0x00, 0x00}, {/* 0xa7 */ 0x00, 0x00, 0x00},
+ {/* 0xa8 */ 0x00, 0x00, 0x00}, {/* 0xa9 */ 0x00, 0x00, 0x00},
+ {/* 0xaa */ 0x00, 0x00, 0x00}, {/* 0xab */ 0x00, 0x00, 0x00},
+ {/* 0xac */ 0x00, 0x00, 0x00}, {/* 0xad */ 0x00, 0x00, 0x00},
+ {/* 0xae */ 0x00, 0x00, 0x00}, {/* 0xaf */ 0x00, 0x00, 0x00},
+ {/* 0xb0 */ 0x00, 0x00, 0x00}, {/* 0xb1 */ 0x00, 0x00, 0x00},
+ {/* 0xb2 */ 0x00, 0x00, 0x00}, {/* 0xb3 */ 0x00, 0x00, 0x00},
+ {/* 0xb4 */ 0x00, 0x00, 0x00}, {/* 0xb5 */ 0x00, 0x00, 0x00},
+ {/* 0xb6 */ 0x00, 0x00, 0x00}, {/* 0xb7 */ 0x00, 0x00, 0x00},
+ {/* 0xb8 */ 0x00, 0x00, 0x00}, {/* 0xb9 */ 0x00, 0x00, 0x00},
+ {/* 0xba */ 0x00, 0x00, 0x00}, {/* 0xbb */ 0x00, 0x00, 0x00},
+ {/* 0xbc */ 0x00, 0x00, 0x00}, {/* 0xbd */ 0x00, 0x00, 0x00},
+ {/* 0xbe */ 0x00, 0x00, 0x00}, {/* 0xbf */ 0x00, 0x00, 0x00},
+ {/* 0xc0 */ 0x00, 0x00, 0x00}, {/* 0xc1 */ 0x00, 0x00, 0x00},
+ {/* 0xc2 */ 0x00, 0x00, 0x00}, {/* 0xc3 */ 0x00, 0x00, 0x00},
+ {/* 0xc4 */ 0x00, 0x00, 0x00}, {/* 0xc5 */ 0x00, 0x00, 0x00},
+ {/* 0xc6 */ 0x00, 0x00, 0x00}, {/* 0xc7 */ 0x00, 0x00, 0x00},
+ {/* 0xc8 */ 0x00, 0x00, 0x00}, {/* 0xc9 */ 0x00, 0x00, 0x00},
+ {/* 0xca */ 0x00, 0x00, 0x00}, {/* 0xcb */ 0x00, 0x00, 0x00},
+ {/* 0xcc */ 0x00, 0x00, 0x00}, {/* 0xcd */ 0x00, 0x00, 0x00},
+ {/* 0xce */ 0x00, 0x00, 0x00}, {/* 0xcf */ 0x00, 0x00, 0x00},
+ {/* 0xd0 */ 0x00, 0x00, 0x00}, {/* 0xd1 */ 0x00, 0x00, 0x00},
+ {/* 0xd2 */ 0x00, 0x00, 0x00}, {/* 0xd3 */ 0x00, 0x00, 0x00},
+ {/* 0xd4 */ 0x00, 0x00, 0x00}, {/* 0xd5 */ 0x00, 0x00, 0x00},
+ {/* 0xd6 */ 0x00, 0x00, 0x00}, {/* 0xd7 */ 0x00, 0x00, 0x00},
+ {/* 0xd8 */ 0x00, 0x00, 0x00}, {/* 0xd9 */ 0x00, 0x00, 0x00},
+ {/* 0xda */ 0x00, 0x00, 0x00}, {/* 0xdb */ 0x00, 0x00, 0x00},
+ {/* 0xdc */ 0x00, 0x00, 0x00}, {/* 0xdd */ 0x00, 0x00, 0x00},
+ {/* 0xde */ 0x00, 0x00, 0x00}, {/* 0xdf */ 0x00, 0x00, 0x00},
+ {/* 0xe0 */ 0x00, 0x00, 0x00}, {/* 0xe1 */ 0x00, 0x00, 0x00},
+ {/* 0xe2 */ 0x00, 0x00, 0x00}, {/* 0xe3 */ 0x00, 0x00, 0x00},
+ {/* 0xe4 */ 0x00, 0x00, 0x00}, {/* 0xe5 */ 0x00, 0x00, 0x00},
+ {/* 0xe6 */ 0x00, 0x00, 0x00}, {/* 0xe7 */ 0x00, 0x00, 0x00},
+ {/* 0xe8 */ 0x00, 0x00, 0x00}, {/* 0xe9 */ 0x00, 0x00, 0x00},
+ {/* 0xea */ 0x00, 0x00, 0x00}, {/* 0xeb */ 0x00, 0x00, 0x00},
+ {/* 0xec */ 0x00, 0x00, 0x00}, {/* 0xed */ 0x00, 0x00, 0x00},
+ {/* 0xee */ 0x00, 0x00, 0x00}, {/* 0xef */ 0x00, 0x00, 0x00},
+ {/* 0xf0 */ 0x00, 0x00, 0x00}, {/* 0xf1 */ 0x00, 0x00, 0x00},
+ {/* 0xf2 */ 0x00, 0x00, 0x00}, {/* 0xf3 */ 0x00, 0x00, 0x00},
+ {/* 0xf4 */ 0x00, 0x00, 0x00}, {/* 0xf5 */ 0x00, 0x00, 0x00},
+ {/* 0xf6 */ 0x00, 0x00, 0x00}, {/* 0xf7 */ 0x00, 0x00, 0x00},
+ {/* 0xf8 */ 0x00, 0x00, 0x00}, {/* 0xf9 */ 0x00, 0x00, 0x00},
+ {/* 0xfa */ 0x00, 0x00, 0x00}, {/* 0xfb */ 0x00, 0x00, 0x00},
+ {/* 0xfc */ 0x00, 0x00, 0x00}, {/* 0xfd */ 0x00, 0x00, 0x00},
+ {/* 0xfe */ 0x00, 0x00, 0x00}, {/* 0xff */ 0x00, 0x00, 0x00}};
+
+const bool sexp_char_defs_t::base64digit[256] =
+ {/* c is base64 digit */
+ /* 0x00 */ false, /* 0x01 */ false, /* 0x02 */ false,
+ /* 0x03 */ false, /* 0x04 */ false, /* 0x05 */ false,
+ /* 0x06 */ false, /* 0x07 */ false, /* 0x08 */ false,
+ /* 0x09 */ false, /* 0x0a */ false, /* 0x0b */ false,
+ /* 0x0c */ false, /* 0x0d */ false, /* 0x0e */ false,
+ /* 0x0f */ false, /* 0x10 */ false, /* 0x11 */ false,
+ /* 0x12 */ false, /* 0x13 */ false, /* 0x14 */ false,
+ /* 0x15 */ false, /* 0x16 */ false, /* 0x17 */ false,
+ /* 0x18 */ false, /* 0x19 */ false, /* 0x1a */ false,
+ /* 0x1b */ false, /* 0x1c */ false, /* 0x1d */ false,
+ /* 0x1e */ false, /* 0x1f */ false, /* 0x20 */ false,
+ /* 0x21 ! */ false, /* 0x22 " */ false, /* 0x23 # */ false,
+ /* 0x24 $ */ false, /* 0x25 % */ false, /* 0x26 & */ false,
+ /* 0x27 ' */ false, /* 0x28 ( */ false, /* 0x29 ) */ false,
+ /* 0x2a * */ false, /* 0x2b + */ true, /* 0x2c , */ false,
+ /* 0x2d - */ false, /* 0x2e . */ false, /* 0x2f / */ true,
+ /* 0x30 0 */ true, /* 0x31 1 */ true, /* 0x32 2 */ true,
+ /* 0x33 3 */ true, /* 0x34 4 */ true, /* 0x35 5 */ true,
+ /* 0x36 6 */ true, /* 0x37 7 */ true, /* 0x38 8 */ true,
+ /* 0x39 9 */ true, /* 0x3a : */ false, /* 0x3b ; */ false,
+ /* 0x3c < */ false, /* 0x3d = */ false, /* 0x3e > */ false,
+ /* 0x3f ? */ false, /* 0x40 @ */ false, /* 0x41 A */ true,
+ /* 0x42 B */ true, /* 0x43 C */ true, /* 0x44 D */ true,
+ /* 0x45 E */ true, /* 0x46 F */ true, /* 0x47 G */ true,
+ /* 0x48 H */ true, /* 0x49 I */ true, /* 0x4a J */ true,
+ /* 0x4b K */ true, /* 0x4c L */ true, /* 0x4d M */ true,
+ /* 0x4e N */ true, /* 0x4f O */ true, /* 0x50 P */ true,
+ /* 0x51 Q */ true, /* 0x52 R */ true, /* 0x53 S */ true,
+ /* 0x54 T */ true, /* 0x55 U */ true, /* 0x56 V */ true,
+ /* 0x57 W */ true, /* 0x58 X */ true, /* 0x59 Y */ true,
+ /* 0x5a Z */ true, /* 0x5b [ */ false, /* 0x5c \ */ false,
+ /* 0x5d ] */ false, /* 0x5e ^ */ false, /* 0x5f _ */ false,
+ /* 0x60 ` */ false, /* 0x61 a */ true, /* 0x62 b */ true,
+ /* 0x63 c */ true, /* 0x64 d */ true, /* 0x65 e */ true,
+ /* 0x66 f */ true, /* 0x67 g */ true, /* 0x68 h */ true,
+ /* 0x69 i */ true, /* 0x6a j */ true, /* 0x6b k */ true,
+ /* 0x6c l */ true, /* 0x6d m */ true, /* 0x6e n */ true,
+ /* 0x6f o */ true, /* 0x70 p */ true, /* 0x71 q */ true,
+ /* 0x72 r */ true, /* 0x73 s */ true, /* 0x74 t */ true,
+ /* 0x75 u */ true, /* 0x76 v */ true, /* 0x77 w */ true,
+ /* 0x78 x */ true, /* 0x79 y */ true, /* 0x7a z */ true,
+ /* 0x7b { */ false, /* 0x7c | */ false, /* 0x7d } */ false,
+ /* 0x7e ~ */ false, /* 0x7f */ false, /* 0x80 */ false,
+ /* 0x81 */ false, /* 0x82 */ false, /* 0x83 */ false,
+ /* 0x84 */ false, /* 0x85 */ false, /* 0x86 */ false,
+ /* 0x87 */ false, /* 0x88 */ false, /* 0x89 */ false,
+ /* 0x8a */ false, /* 0x8b */ false, /* 0x8c */ false,
+ /* 0x8d */ false, /* 0x8e */ false, /* 0x8f */ false,
+ /* 0x90 */ false, /* 0x91 */ false, /* 0x92 */ false,
+ /* 0x93 */ false, /* 0x94 */ false, /* 0x95 */ false,
+ /* 0x96 */ false, /* 0x97 */ false, /* 0x98 */ false,
+ /* 0x99 */ false, /* 0x9a */ false, /* 0x9b */ false,
+ /* 0x9c */ false, /* 0x9d */ false, /* 0x9e */ false,
+ /* 0x9f */ false, /* 0xa0 */ false, /* 0xa1 */ false,
+ /* 0xa2 */ false, /* 0xa3 */ false, /* 0xa4 */ false,
+ /* 0xa5 */ false, /* 0xa6 */ false, /* 0xa7 */ false,
+ /* 0xa8 */ false, /* 0xa9 */ false, /* 0xaa */ false,
+ /* 0xab */ false, /* 0xac */ false, /* 0xad */ false,
+ /* 0xae */ false, /* 0xaf */ false, /* 0xb0 */ false,
+ /* 0xb1 */ false, /* 0xb2 */ false, /* 0xb3 */ false,
+ /* 0xb4 */ false, /* 0xb5 */ false, /* 0xb6 */ false,
+ /* 0xb7 */ false, /* 0xb8 */ false, /* 0xb9 */ false,
+ /* 0xba */ false, /* 0xbb */ false, /* 0xbc */ false,
+ /* 0xbd */ false, /* 0xbe */ false, /* 0xbf */ false,
+ /* 0xc0 */ false, /* 0xc1 */ false, /* 0xc2 */ false,
+ /* 0xc3 */ false, /* 0xc4 */ false, /* 0xc5 */ false,
+ /* 0xc6 */ false, /* 0xc7 */ false, /* 0xc8 */ false,
+ /* 0xc9 */ false, /* 0xca */ false, /* 0xcb */ false,
+ /* 0xcc */ false, /* 0xcd */ false, /* 0xce */ false,
+ /* 0xcf */ false, /* 0xd0 */ false, /* 0xd1 */ false,
+ /* 0xd2 */ false, /* 0xd3 */ false, /* 0xd4 */ false,
+ /* 0xd5 */ false, /* 0xd6 */ false, /* 0xd7 */ false,
+ /* 0xd8 */ false, /* 0xd9 */ false, /* 0xda */ false,
+ /* 0xdb */ false, /* 0xdc */ false, /* 0xdd */ false,
+ /* 0xde */ false, /* 0xdf */ false, /* 0xe0 */ false,
+ /* 0xe1 */ false, /* 0xe2 */ false, /* 0xe3 */ false,
+ /* 0xe4 */ false, /* 0xe5 */ false, /* 0xe6 */ false,
+ /* 0xe7 */ false, /* 0xe8 */ false, /* 0xe9 */ false,
+ /* 0xea */ false, /* 0xeb */ false, /* 0xec */ false,
+ /* 0xed */ false, /* 0xee */ false, /* 0xef */ false,
+ /* 0xf0 */ false, /* 0xf1 */ false, /* 0xf2 */ false,
+ /* 0xf3 */ false, /* 0xf4 */ false, /* 0xf5 */ false,
+ /* 0xf6 */ false, /* 0xf7 */ false, /* 0xf8 */ false,
+ /* 0xf9 */ false, /* 0xfa */ false, /* 0xfb */ false,
+ /* 0xfc */ false, /* 0xfd */ false, /* 0xfe */ false};
+
+const bool sexp_char_defs_t::tokenchar[256] =
+ {/* c can be in a token */
+ /* 0x00 */ false, /* 0x01 */ false, /* 0x02 */ false,
+ /* 0x03 */ false, /* 0x04 */ false, /* 0x05 */ false,
+ /* 0x06 */ false, /* 0x07 */ false, /* 0x08 */ false,
+ /* 0x09 */ false, /* 0x0a */ false, /* 0x0b */ false,
+ /* 0x0c */ false, /* 0x0d */ false, /* 0x0e */ false,
+ /* 0x0f */ false, /* 0x10 */ false, /* 0x11 */ false,
+ /* 0x12 */ false, /* 0x13 */ false, /* 0x14 */ false,
+ /* 0x15 */ false, /* 0x16 */ false, /* 0x17 */ false,
+ /* 0x18 */ false, /* 0x19 */ false, /* 0x1a */ false,
+ /* 0x1b */ false, /* 0x1c */ false, /* 0x1d */ false,
+ /* 0x1e */ false, /* 0x1f */ false, /* 0x20 */ false,
+ /* 0x21 ! */ false, /* 0x22 " */ false, /* 0x23 # */ false,
+ /* 0x24 $ */ false, /* 0x25 % */ false, /* 0x26 & */ false,
+ /* 0x27 ' */ false, /* 0x28 ( */ false, /* 0x29 ) */ false,
+ /* 0x2a * */ true, /* 0x2b + */ true, /* 0x2c , */ false,
+ /* 0x2d - */ true, /* 0x2e . */ true, /* 0x2f / */ true,
+ /* 0x30 0 */ true, /* 0x31 1 */ true, /* 0x32 2 */ true,
+ /* 0x33 3 */ true, /* 0x34 4 */ true, /* 0x35 5 */ true,
+ /* 0x36 6 */ true, /* 0x37 7 */ true, /* 0x38 8 */ true,
+ /* 0x39 9 */ true, /* 0x3a : */ true, /* 0x3b ; */ false,
+ /* 0x3c < */ false, /* 0x3d = */ true, /* 0x3e > */ false,
+ /* 0x3f ? */ false, /* 0x40 @ */ false, /* 0x41 A */ true,
+ /* 0x42 B */ true, /* 0x43 C */ true, /* 0x44 D */ true,
+ /* 0x45 E */ true, /* 0x46 F */ true, /* 0x47 G */ true,
+ /* 0x48 H */ true, /* 0x49 I */ true, /* 0x4a J */ true,
+ /* 0x4b K */ true, /* 0x4c L */ true, /* 0x4d M */ true,
+ /* 0x4e N */ true, /* 0x4f O */ true, /* 0x50 P */ true,
+ /* 0x51 Q */ true, /* 0x52 R */ true, /* 0x53 S */ true,
+ /* 0x54 T */ true, /* 0x55 U */ true, /* 0x56 V */ true,
+ /* 0x57 W */ true, /* 0x58 X */ true, /* 0x59 Y */ true,
+ /* 0x5a Z */ true, /* 0x5b [ */ false, /* 0x5c \ */ false,
+ /* 0x5d ] */ false, /* 0x5e ^ */ false, /* 0x5f _ */ true,
+ /* 0x60 ` */ false, /* 0x61 a */ true, /* 0x62 b */ true,
+ /* 0x63 c */ true, /* 0x64 d */ true, /* 0x65 e */ true,
+ /* 0x66 f */ true, /* 0x67 g */ true, /* 0x68 h */ true,
+ /* 0x69 i */ true, /* 0x6a j */ true, /* 0x6b k */ true,
+ /* 0x6c l */ true, /* 0x6d m */ true, /* 0x6e n */ true,
+ /* 0x6f o */ true, /* 0x70 p */ true, /* 0x71 q */ true,
+ /* 0x72 r */ true, /* 0x73 s */ true, /* 0x74 t */ true,
+ /* 0x75 u */ true, /* 0x76 v */ true, /* 0x77 w */ true,
+ /* 0x78 x */ true, /* 0x79 y */ true, /* 0x7a z */ true,
+ /* 0x7b { */ false, /* 0x7c | */ false, /* 0x7d } */ false,
+ /* 0x7e ~ */ false, /* 0x7f */ false, /* 0x80 */ false,
+ /* 0x81 */ false, /* 0x82 */ false, /* 0x83 */ false,
+ /* 0x84 */ false, /* 0x85 */ false, /* 0x86 */ false,
+ /* 0x87 */ false, /* 0x88 */ false, /* 0x89 */ false,
+ /* 0x8a */ false, /* 0x8b */ false, /* 0x8c */ false,
+ /* 0x8d */ false, /* 0x8e */ false, /* 0x8f */ false,
+ /* 0x90 */ false, /* 0x91 */ false, /* 0x92 */ false,
+ /* 0x93 */ false, /* 0x94 */ false, /* 0x95 */ false,
+ /* 0x96 */ false, /* 0x97 */ false, /* 0x98 */ false,
+ /* 0x99 */ false, /* 0x9a */ false, /* 0x9b */ false,
+ /* 0x9c */ false, /* 0x9d */ false, /* 0x9e */ false,
+ /* 0x9f */ false, /* 0xa0 */ false, /* 0xa1 */ false,
+ /* 0xa2 */ false, /* 0xa3 */ false, /* 0xa4 */ false,
+ /* 0xa5 */ false, /* 0xa6 */ false, /* 0xa7 */ false,
+ /* 0xa8 */ false, /* 0xa9 */ false, /* 0xaa */ false,
+ /* 0xab */ false, /* 0xac */ false, /* 0xad */ false,
+ /* 0xae */ false, /* 0xaf */ false, /* 0xb0 */ false,
+ /* 0xb1 */ false, /* 0xb2 */ false, /* 0xb3 */ false,
+ /* 0xb4 */ false, /* 0xb5 */ false, /* 0xb6 */ false,
+ /* 0xb7 */ false, /* 0xb8 */ false, /* 0xb9 */ false,
+ /* 0xba */ false, /* 0xbb */ false, /* 0xbc */ false,
+ /* 0xbd */ false, /* 0xbe */ false, /* 0xbf */ false,
+ /* 0xc0 */ false, /* 0xc1 */ false, /* 0xc2 */ false,
+ /* 0xc3 */ false, /* 0xc4 */ false, /* 0xc5 */ false,
+ /* 0xc6 */ false, /* 0xc7 */ false, /* 0xc8 */ false,
+ /* 0xc9 */ false, /* 0xca */ false, /* 0xcb */ false,
+ /* 0xcc */ false, /* 0xcd */ false, /* 0xce */ false,
+ /* 0xcf */ false, /* 0xd0 */ false, /* 0xd1 */ false,
+ /* 0xd2 */ false, /* 0xd3 */ false, /* 0xd4 */ false,
+ /* 0xd5 */ false, /* 0xd6 */ false, /* 0xd7 */ false,
+ /* 0xd8 */ false, /* 0xd9 */ false, /* 0xda */ false,
+ /* 0xdb */ false, /* 0xdc */ false, /* 0xdd */ false,
+ /* 0xde */ false, /* 0xdf */ false, /* 0xe0 */ false,
+ /* 0xe1 */ false, /* 0xe2 */ false, /* 0xe3 */ false,
+ /* 0xe4 */ false, /* 0xe5 */ false, /* 0xe6 */ false,
+ /* 0xe7 */ false, /* 0xe8 */ false, /* 0xe9 */ false,
+ /* 0xea */ false, /* 0xeb */ false, /* 0xec */ false,
+ /* 0xed */ false, /* 0xee */ false, /* 0xef */ false,
+ /* 0xf0 */ false, /* 0xf1 */ false, /* 0xf2 */ false,
+ /* 0xf3 */ false, /* 0xf4 */ false, /* 0xf5 */ false,
+ /* 0xf6 */ false, /* 0xf7 */ false, /* 0xf8 */ false,
+ /* 0xf9 */ false, /* 0xfa */ false, /* 0xfb */ false,
+ /* 0xfc */ false, /* 0xfd */ false, /* 0xfe */ false};
+
+} // namespace sexp
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-error.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-error.cpp
new file mode 100644
index 0000000000..992b680405
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-error.cpp
@@ -0,0 +1,62 @@
+/**
+ *
+ * Copyright (c) 2022, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sexp/sexp-error.h>
+
+namespace sexp {
+
+sexp_exception_t::severity sexp_exception_t::verbosity = sexp_exception_t::error;
+bool sexp_exception_t::interactive = false;
+
+std::string sexp_exception_t::format(std::string prf,
+ std::string message,
+ severity level,
+ int position)
+{
+ std::string r = prf + (level == error ? " ERROR: " : " WARNING: ") + message;
+ if (position >= 0)
+ r += " at position " + std::to_string(position);
+ return r;
+};
+
+void sexp_error(
+ sexp_exception_t::severity level, const char *msg, size_t c1, size_t c2, int pos)
+{
+ char tmp[256];
+ sexp_exception_t::severity l = (sexp_exception_t::severity) level;
+ snprintf(tmp, sizeof(tmp) / sizeof(tmp[0]), msg, c1, c2);
+ if (sexp_exception_t::shall_throw(l))
+ throw sexp_exception_t(tmp, l, pos);
+ if (sexp_exception_t::is_interactive()) {
+ std::cout.flush() << std::endl
+ << "*** " << sexp_exception_t::format("SEXP", tmp, l, pos) << " ***"
+ << std::endl;
+ }
+}
+} // namespace sexp \ No newline at end of file
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-input.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-input.cpp
new file mode 100644
index 0000000000..daa8984551
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-input.cpp
@@ -0,0 +1,507 @@
+/**
+ *
+ * Copyright (c) 2022-2023, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP implementation code sexp-input.c
+ * Ron Rivest
+ * 7/21/1997
+ */
+
+#include <sexp/sexp.h>
+
+namespace sexp {
+
+/*
+ * newSexpInputStream()
+ * Creates and initializes a new sexp_input_stream_t object.
+ * (Prefixes stream with one blank, and initializes stream
+ * so that it reads from standard input.)
+ */
+std::istream *input_file;
+uint32_t byte_size; /* 4 or 6 or 8 == currently scanning mode */
+int next_char; /* character currently being scanned */
+uint32_t bits; /* Bits waiting to be used */
+uint32_t n_bits; /* number of such bits waiting to be used */
+int count; /* number of 8-bit characters output by get_char */
+
+sexp_input_stream_t::sexp_input_stream_t(std::istream *i, size_t m_depth)
+{
+ set_input(i, m_depth);
+}
+
+/*
+ * sexp_input_stream_t::set_input(std::istream *i)
+ */
+
+sexp_input_stream_t *sexp_input_stream_t::set_input(std::istream *i, size_t m_depth)
+{
+ input_file = i;
+ byte_size = 8;
+ next_char = ' ';
+ bits = 0;
+ n_bits = 0;
+ count = -1;
+ depth = 0;
+ max_depth = m_depth;
+ return this;
+}
+
+/*
+ * sexp_input_stream_t::set_byte_size(newByteSize)
+ */
+sexp_input_stream_t *sexp_input_stream_t::set_byte_size(uint32_t newByteSize)
+{
+ byte_size = newByteSize;
+ n_bits = 0;
+ bits = 0;
+ return this;
+}
+
+int sexp_input_stream_t::read_char(void)
+{
+ count++;
+ return input_file->get();
+}
+
+/*
+ * sexp_input_stream_t::get_char()
+ * This is one possible character input routine for an input stream.
+ * (This version uses the standard input stream.)
+ * get_char places next 8-bit character into is->next_char.
+ * It also updates the count of number of 8-bit characters read.
+ * The value EOF is obtained when no more input is available.
+ * This code handles 4-bit/6-bit/8-bit channels.
+ */
+sexp_input_stream_t *sexp_input_stream_t::get_char(void)
+{
+ int c;
+ if (next_char == EOF) {
+ byte_size = 8;
+ return this;
+ }
+
+ while (true) {
+ c = next_char = read_char();
+ if (c == EOF)
+ return this;
+ if ((byte_size == 6 && (c == '|' || c == '}')) || (byte_size == 4 && (c == '#'))) {
+ // end of region reached; return terminating character, after checking for
+ // unused bits
+ if (n_bits > 0 && (((1 << n_bits) - 1) & bits) != 0) {
+ sexp_error(sexp_exception_t::warning,
+ "%d-bit region ended with %d unused bits left-over",
+ byte_size,
+ n_bits,
+ count);
+ }
+ return set_byte_size(8);
+ } else if (byte_size != 8 && is_white_space(c))
+ ; /* ignore white space in hex and base64 regions */
+ else if (byte_size == 6 && c == '=')
+ ; /* ignore equals signs in base64 regions */
+ else if (byte_size == 8) {
+ return this;
+ } else if (byte_size < 8) {
+ bits = bits << byte_size;
+ n_bits += byte_size;
+ if (byte_size == 6 && is_base64_digit(c))
+ bits = bits | base64value(c);
+ else if (byte_size == 4 && is_hex_digit(c))
+ bits = bits | hexvalue(c);
+ else {
+ sexp_error(sexp_exception_t::error,
+ "character '%c' found in %u-bit coding region",
+ next_char,
+ byte_size,
+ count);
+ }
+ if (n_bits >= 8) {
+ next_char = (bits >> (n_bits - 8)) & 0xFF;
+ n_bits -= 8;
+ return this;
+ }
+ }
+ }
+}
+
+/*
+ * sexp_input_stream_t::skip_white_space
+ * Skip over any white space on the given sexp_input_stream_t.
+ */
+sexp_input_stream_t *sexp_input_stream_t::skip_white_space(void)
+{
+ while (is_white_space(next_char))
+ get_char();
+ return this;
+}
+
+/*
+ * sexp_input_stream_t::skip_char(c)
+ * Skip the following input character on input stream is, if it is
+ * equal to the character c. If it is not equal, then an error occurs.
+ */
+sexp_input_stream_t *sexp_input_stream_t::skip_char(int c)
+{
+ if (next_char != c)
+ sexp_error(sexp_exception_t::error,
+ "character '%c' found where '%c' was expected",
+ next_char,
+ c,
+ count);
+ return get_char();
+}
+
+/*
+ * sexp_input_stream_t::scan_token(ss)
+ * scan one or more characters into simple string ss as a token.
+ */
+void sexp_input_stream_t::scan_token(sexp_simple_string_t &ss)
+{
+ skip_white_space();
+ while (is_token_char(next_char)) {
+ ss.append(next_char);
+ get_char();
+ }
+}
+
+/*
+ * sexp_input_stream_t::scan_to_eof(void)
+ * scan one or more characters (until EOF reached)
+ * return an object that is just that string
+ */
+std::shared_ptr<sexp_object_t> sexp_input_stream_t::scan_to_eof(void)
+{
+ sexp_simple_string_t ss;
+ std::shared_ptr<sexp_string_t> s(new sexp_string_t());
+ skip_white_space();
+ while (next_char != EOF) {
+ ss.append(next_char);
+ get_char();
+ }
+ s->set_string(ss);
+ return s;
+}
+
+/*
+ * scan_decimal_string(is)
+ * returns long integer that is value of decimal number
+ */
+uint32_t sexp_input_stream_t::scan_decimal_string(void)
+{
+ uint32_t value = 0;
+ uint32_t i = 0;
+ while (is_dec_digit(next_char)) {
+ value = value * 10 + decvalue(next_char);
+ get_char();
+ if (i++ > 8)
+ sexp_error(sexp_exception_t::error, "Decimal number is too long", 0, 0, count);
+ }
+ return value;
+}
+
+/*
+ * sexp_input_stream_t::scan_verbatim_string(is,ss,length)
+ * Reads verbatim string of given length into simple string ss.
+ */
+void sexp_input_stream_t::scan_verbatim_string(sexp_simple_string_t &ss, uint32_t length)
+{
+ skip_white_space()->skip_char(':');
+
+ // Some length is specified always, this is ensured by the caller's logic
+ assert(length != std::numeric_limits<uint32_t>::max());
+ for (uint32_t i = 0; i < length; i++) {
+ ss.append(next_char);
+ get_char();
+ }
+}
+
+/*
+ * sexp_input_stream_t::scan_quoted_string(ss,length)
+ * Reads quoted string of given length into simple string ss.
+ * Handles ordinary C escapes.
+ * If of indefinite length, length is std::numeric_limits<uint32_t>::max().
+ */
+void sexp_input_stream_t::scan_quoted_string(sexp_simple_string_t &ss, uint32_t length)
+{
+ skip_char('"');
+ while (ss.length() <= length) {
+ if (next_char == '\"') {
+ if (length == std::numeric_limits<uint32_t>::max() || (ss.length() == length)) {
+ skip_char('\"');
+ return;
+ } else
+ sexp_error(sexp_exception_t::error,
+ "Declared length was %d, but quoted string ended too early",
+ (int) length,
+ 0,
+ count);
+ } else if (next_char == '\\') /* handle escape sequence */
+ {
+ get_char();
+ switch (next_char) {
+ case 'b':
+ ss.append('\b');
+ break;
+ case 't':
+ ss.append('\t');
+ break;
+ case 'v':
+ ss.append('\v');
+ break;
+ case 'n':
+ ss.append('\n');
+ break;
+ case 'f':
+ ss.append('\f');
+ break;
+ case 'r':
+ ss.append('\r');
+ break;
+ case '\"':
+ ss.append('\"');
+ break;
+ case '\'':
+ ss.append('\'');
+ break;
+ case '\\':
+ ss.append('\\');
+ break;
+ case 'x': /* hexadecimal number */
+ {
+ int j, val;
+ val = 0;
+ get_char();
+ for (j = 0; j < 2; j++) {
+ if (is_hex_digit(next_char)) {
+ val = ((val << 4) | hexvalue(next_char));
+ if (j < 1) {
+ get_char();
+ }
+ } else
+ sexp_error(sexp_exception_t::error,
+ "Hex character \x5cx%x... too short",
+ val,
+ 0,
+ count);
+ }
+ ss.append(val);
+ } break;
+ case '\n': /* ignore backslash line feed */
+ get_char(); /* also ignore following carriage-return if present */
+ if (next_char != '\r')
+ continue;
+ break;
+ case '\r': /* ignore backslash carriage-return */
+ get_char(); /* also ignore following linefeed if present */
+ if (next_char != '\n')
+ continue;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': { /* octal number */
+ int j, val;
+ val = 0;
+ for (j = 0; j < 3; j++) {
+ if (next_char >= '0' && next_char <= '7') {
+ val = ((val << 3) | (next_char - '0'));
+ if (j < 2)
+ get_char();
+ } else
+ sexp_error(sexp_exception_t::error,
+ "Octal character \\%o... too short",
+ val,
+ 0,
+ count);
+ }
+ if (val > 255)
+ sexp_error(sexp_exception_t::error,
+ "Octal character \\%o... too big",
+ val,
+ 0,
+ count);
+ ss.append(val);
+ } break;
+ default:
+ sexp_error(sexp_exception_t::error,
+ "Unknown escape sequence \\%c",
+ next_char,
+ 0,
+ count);
+ }
+ } /* end of handling escape sequence */
+ else if (next_char == EOF) {
+ sexp_error(sexp_exception_t::error, "unexpected end of file", 0, 0, count);
+ } else {
+ ss.append(next_char);
+ }
+ get_char();
+ } /* end of main while loop */
+}
+
+/*
+ * scan_hexadecimal_string(ss,length)
+ * Reads hexadecimal string into simple string ss.
+ * String is of given length result, or length = std::numeric_limits<uint32_t>::max()
+ * if indefinite length.
+ */
+void sexp_input_stream_t::scan_hexadecimal_string(sexp_simple_string_t &ss, uint32_t length)
+{
+ set_byte_size(4)->skip_char('#');
+ while (next_char != EOF && (next_char != '#' || get_byte_size() == 4)) {
+ ss.append(next_char);
+ get_char();
+ }
+ skip_char('#');
+ if (ss.length() != length && length != std::numeric_limits<uint32_t>::max())
+ sexp_error(sexp_exception_t::warning,
+ "Hex string has length %d different than declared length %d",
+ ss.length(),
+ length,
+ count);
+}
+
+/*
+ * sexp_input_stream_t::scan_base64_string(ss,length)
+ * Reads base64 string into simple string ss.
+ * String is of given length result, or length = std::numeric_limits<uint32_t>::max()
+ * if indefinite length.
+ */
+void sexp_input_stream_t::scan_base64_string(sexp_simple_string_t &ss, uint32_t length)
+{
+ set_byte_size(6)->skip_char('|');
+ while (next_char != EOF && (next_char != '|' || get_byte_size() == 6)) {
+ ss.append(next_char);
+ get_char();
+ }
+ skip_char('|');
+ if (ss.length() != length && length != std::numeric_limits<uint32_t>::max())
+ sexp_error(sexp_exception_t::warning,
+ "Base64 string has length %d different than declared length %d",
+ ss.length(),
+ length,
+ count);
+}
+
+/*
+ * sexp_input_stream_t::scan_simple_string(void)
+ * Reads and returns a simple string from the input stream.
+ * Determines type of simple string from the initial character, and
+ * dispatches to appropriate routine based on that.
+ */
+sexp_simple_string_t sexp_input_stream_t::scan_simple_string(void)
+{
+ int length;
+ sexp_simple_string_t ss;
+ skip_white_space();
+ /* Note that it is important in the following code to test for token-ness
+ * before checking the other cases, so that a token may begin with ":",
+ * which would otherwise be treated as a verbatim string missing a length.
+ */
+ if (is_token_char(next_char) && !is_dec_digit(next_char)) {
+ scan_token(ss);
+ } else {
+ length = is_dec_digit(next_char) ? scan_decimal_string() :
+ std::numeric_limits<uint32_t>::max();
+
+ switch (next_char) {
+ case '\"':
+ scan_quoted_string(ss, length);
+ break;
+ case '#':
+ scan_hexadecimal_string(ss, length);
+ break;
+ case '|':
+ scan_base64_string(ss, length);
+ break;
+ case ':':
+ // ':' is 'tokenchar', so some length shall be defined
+ scan_verbatim_string(ss, length);
+ break;
+ default: {
+ const char *const msg = (next_char == EOF) ? "unexpected end of file" :
+ isprint(next_char) ? "illegal character '%c' (0x%x)" :
+ "illegal character 0x%x";
+ sexp_error(sexp_exception_t::error, msg, next_char, next_char, count);
+ }
+ }
+ }
+
+ if (ss.length() == 0)
+ sexp_error(sexp_exception_t::warning, "Simple string has zero length", 0, 0, count);
+ return ss;
+}
+
+/*
+ * sexp_input_stream_t::scan_string(void)
+ * Reads and returns a string [presentationhint]string from input stream.
+ */
+std::shared_ptr<sexp_string_t> sexp_input_stream_t::scan_string(void)
+{
+ std::shared_ptr<sexp_string_t> s(new sexp_string_t());
+ s->parse(this);
+ return s;
+}
+
+/*
+ * sexp_input_stream_t::scan_list(void)
+ * Read and return a sexp_list_t from the input stream.
+ */
+std::shared_ptr<sexp_list_t> sexp_input_stream_t::scan_list(void)
+{
+ std::shared_ptr<sexp_list_t> list(new sexp_list_t());
+ list->parse(this);
+ return list;
+}
+
+/*
+ * sexp_input_stream_t::scan_object(void)
+ * Reads and returns a sexp_object_t from the given input stream.
+ */
+std::shared_ptr<sexp_object_t> sexp_input_stream_t::scan_object(void)
+{
+ std::shared_ptr<sexp_object_t> object;
+ skip_white_space();
+ if (next_char == '{' && byte_size != 6) {
+ set_byte_size(6)->skip_char('{');
+ object = scan_object();
+ skip_char('}');
+ } else {
+ if (next_char == '(')
+ object = scan_list();
+ else
+ object = scan_string();
+ }
+ return object;
+}
+
+} // namespace sexp
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-main.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-main.cpp
new file mode 100644
index 0000000000..7406bdfd5e
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-main.cpp
@@ -0,0 +1,237 @@
+/**
+ *
+ * Copyright (c) 2022-2023, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ *CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ *IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP implementation code sexp-main.c
+ * Ron Rivest
+ * 6/29/1997
+ **/
+
+#include <fstream>
+
+#include <sexp/sexp.h>
+
+using namespace sexp;
+
+const char *help = "The program 'sexp' reads, parses, and prints out S-expressions.\n"
+ " INPUT:\n"
+ " Input is normally taken from stdin, but this can be changed:\n"
+ " -i filename -- takes input from file instead.\n"
+ " -p -- prompts user for console input\n"
+ " Input is normally parsed, but this can be changed:\n"
+ " -s -- treat input up to EOF as a single string\n"
+ " CONTROL LOOP:\n"
+ " The main routine typically reads one S-expression, prints it out "
+ "again, \n"
+ " and stops. This may be modified:\n"
+ " -x -- execute main loop repeatedly until EOF\n"
+ " OUTPUT:\n"
+ " Output is normally written to stdout, but this can be changed:\n"
+ " -o filename -- write output to file instead\n"
+ " The output format is normally canonical, but this can be changed:\n"
+ " -a -- write output in advanced transport format\n"
+ " -b -- write output in base-64 output format\n"
+ " -c -- write output in canonical format\n"
+ " -l -- suppress linefeeds after output\n"
+ " More than one output format can be requested at once.\n"
+ " There is normally a line-width of 75 on output, but:\n"
+ " -w width -- changes line width to specified width.\n"
+ " (0 implies no line-width constraint)\n"
+ " Running without switches implies: -p -a -b -c -x\n"
+ " Typical usage: cat certificate-file | sexp -a -x \n";
+
+/*************************************************************************/
+/* main(argc,argv)
+ */
+int main(int argc, char **argv)
+{
+ char *c;
+ bool swa = true, swb = true, swc = true, swp = true, sws = false, swx = true, swl = false;
+ int i;
+ int ret = -1;
+ sexp_exception_t::set_interactive(true);
+ std::ifstream * ifs = nullptr;
+ sexp_input_stream_t * is = nullptr;
+ std::ofstream * ofs = nullptr;
+ sexp_output_stream_t *os = nullptr;
+ std::string ofname;
+ std::string ifname;
+ try {
+ std::shared_ptr<sexp_object_t> object;
+
+ is = new sexp_input_stream_t(&std::cin);
+ os = new sexp_output_stream_t(&std::cout);
+
+ if (argc > 1)
+ swa = swb = swc = swp = sws = swx = swl = false;
+ for (i = 1; i < argc; i++) {
+ c = argv[i];
+ if (*c != '-')
+ throw sexp_exception_t(
+ std::string("Unrecognized switch ") + c, sexp_exception_t::error, EOF);
+ c++;
+ if (*c == 'a')
+ swa = true; /* advanced output */
+ else if (*c == 'b')
+ swb = true; /* base-64 output */
+ else if (*c == 'c')
+ swc = true; /* canonical output */
+ else if (*c == 'h') { /* help */
+ std::cout << help;
+ exit(0);
+ } else if (*c == 'i') { /* input file */
+ if (i + 1 < argc)
+ i++;
+ ifs = new std::ifstream(argv[i], std::ifstream::binary);
+ if (ifs->fail())
+ sexp_error(sexp_exception_t::error, "Can't open input file.", 0, 0, EOF);
+ is->set_input(ifs);
+ ifname = argv[i];
+ } else if (*c == 'l')
+ swl = true; /* suppress linefeeds after output */
+ else if (*c == 'o') { /* output file */
+ if (i + 1 < argc)
+ i++;
+ ofs = new std::ofstream(argv[i], std::ifstream::binary);
+ if (ofs->fail())
+ sexp_error(sexp_exception_t::error, "Can't open output file.", 0, 0, EOF);
+ os->set_output(ofs);
+ ofname = argv[i];
+ } else if (*c == 'p')
+ swp = true; /* prompt for input */
+ else if (*c == 's')
+ sws = true; /* treat input as one big string */
+ else if (*c == 'w') { /* set output width */
+ if (i + 1 < argc)
+ i++;
+ os->set_max_column(atoi(argv[i]));
+ } else if (*c == 'x')
+ swx = true; /* execute repeatedly */
+ else
+ throw sexp_exception_t(
+ std::string("Unrecognized switch ") + argv[i], sexp_exception_t::error, EOF);
+ }
+
+ if (swa == false && swb == false && swc == false)
+ swc = true; /* must have some output format! */
+
+ /* main loop */
+ if (swp == 0)
+ is->get_char();
+ else
+ is->set_next_char(-2); /* this is not EOF */
+ while (is->get_next_char() != EOF) {
+ if (swp) {
+ if (ifname.empty())
+ std::cout << "Input:";
+ else
+ std::cout << "Reading input from " << ifname;
+ std::cout << std::endl;
+ std::cout.flush();
+ }
+
+ is->set_byte_size(8);
+ if (is->get_next_char() == -2)
+ is->get_char();
+
+ is->skip_white_space();
+ if (is->get_next_char() == EOF)
+ break;
+
+ object = sws ? is->scan_to_eof() : is->scan_object();
+
+ if (swp)
+ std::cout << std::endl;
+
+ if (swc) {
+ if (swp) {
+ if (ofname.empty())
+ std::cout << "Canonical output:" << std::endl;
+ else
+ std::cout << "Writing canonical output to '" << ofname << "'";
+ }
+ object->print_canonical(os);
+ if (!swl) {
+ std::cout << std::endl;
+ }
+ }
+
+ if (swb) {
+ if (swp) {
+ if (ofname.empty())
+ std::cout << "Base64 (of canonical) output:" << std::endl;
+ else
+ std::cout << "Writing base64 (of canonical) output to '" << ofname
+ << "'";
+ }
+ os->set_output(ofs ? ofs : &std::cout)->print_base64(object);
+ if (!swl) {
+ std::cout << std::endl;
+ std::cout.flush();
+ }
+ }
+
+ if (swa) {
+ if (swp) {
+ if (ofname.empty())
+ std::cout << "Advanced transport output:" << std::endl;
+ else
+ std::cout << "Writing advanced transport output to '" << ofname << "'";
+ }
+ os->set_output(ofs ? ofs : &std::cout)->print_advanced(object);
+ if (!swl) {
+ std::cout << std::endl;
+ std::cout.flush();
+ }
+ }
+
+ if (!swx)
+ break;
+ if (!swp)
+ is->skip_white_space();
+ else if (!swl) {
+ std::cout << std::endl;
+ std::cout.flush();
+ }
+ }
+ ret = 0;
+ } catch (sexp_exception_t &e) {
+ std::cout << e.what() << std::endl;
+ } catch (...) {
+ std::cout << "UNEXPECTED ERROR" << std::endl;
+ }
+ if (is)
+ delete is;
+ if (ifs)
+ delete ifs;
+ if (os)
+ delete os;
+ if (ofs)
+ delete ofs;
+ return ret;
+} \ No newline at end of file
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-object.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-object.cpp
new file mode 100644
index 0000000000..4669cb4006
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-object.cpp
@@ -0,0 +1,194 @@
+/**
+ *
+ * Copyright (c) 2022-2023, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP implementation code sexp-output.c
+ * Ron Rivest
+ * 5/5/1997
+ */
+
+#include <sexp/sexp.h>
+
+namespace sexp {
+
+/*
+ * sexp_string_t::parse(sis)
+ * Parses the strin from input stream
+ */
+
+void sexp_string_t::parse(sexp_input_stream_t *sis)
+{
+ if (sis->get_next_char() == '[') { /* scan presentation hint */
+ sis->skip_char('[');
+ set_presentation_hint(sis->scan_simple_string());
+ sis->skip_white_space()->skip_char(']')->skip_white_space();
+ }
+ set_string(sis->scan_simple_string());
+}
+
+/*
+ * sexp_string_t::print_canonical(os)
+ * Prints out sexp string onto output stream os
+ */
+sexp_output_stream_t *sexp_string_t::print_canonical(sexp_output_stream_t *os) const
+{
+ if (with_presentation_hint) {
+ os->var_put_char('[');
+ presentation_hint.print_canonical_verbatim(os);
+ os->var_put_char(']');
+ }
+ data_string.print_canonical_verbatim(os);
+ return os;
+}
+
+/*
+ * sexp_string_t::print_advanced(os)
+ * Prints out sexp string onto output stream os
+ */
+sexp_output_stream_t *sexp_string_t::print_advanced(sexp_output_stream_t *os) const
+{
+ sexp_object_t::print_advanced(os);
+ if (with_presentation_hint) {
+ os->put_char('[');
+ presentation_hint.print_advanced(os);
+ os->put_char(']');
+ }
+ data_string.print_advanced(os);
+ return os;
+}
+
+/*
+ * sexp_string_t::advanced_length(os)
+ * Returns length of printed image of string
+ */
+size_t sexp_string_t::advanced_length(sexp_output_stream_t *os) const
+{
+ size_t len = 0;
+ if (with_presentation_hint)
+ len += 2 + presentation_hint.advanced_length(os);
+ len += data_string.advanced_length(os);
+ return len;
+}
+
+/*
+ * sexp_list_t::parse(sis)
+ * Parses the list from input stream
+ */
+
+void sexp_list_t::parse(sexp_input_stream_t *sis)
+{
+ sis->skip_char('(')->increase_depth()->skip_white_space();
+ if (sis->get_next_char() == ')') {
+ ;
+ } else {
+ push_back(sis->scan_object());
+ }
+
+ while (true) {
+ sis->skip_white_space();
+ if (sis->get_next_char() == ')') { /* we just grabbed last element of list */
+ sis->skip_char(')')->decrease_depth();
+ return;
+
+ } else {
+ push_back(sis->scan_object());
+ }
+ }
+}
+
+/*
+ * sexp_list_t::print_canonical(os)
+ * Prints out the list "list" onto output stream os
+ */
+sexp_output_stream_t *sexp_list_t::print_canonical(sexp_output_stream_t *os) const
+{
+ os->var_put_char('(');
+ std::for_each(begin(), end(), [os](const std::shared_ptr<sexp_object_t> &obj) {
+ obj->print_canonical(os);
+ });
+ os->var_put_char(')');
+ return os;
+}
+
+/*
+ * sexp_list_t::print_advanced(os)
+ * Prints out the list onto output stream os.
+ * Uses print-length to determine length of the image. If it all fits
+ * on the current line, then it is printed that way. Otherwise, it is
+ * written out in "vertical" mode, with items of the list starting in
+ * the same column on successive lines.
+ */
+sexp_output_stream_t *sexp_list_t::print_advanced(sexp_output_stream_t *os) const
+{
+ sexp_object_t::print_advanced(os);
+ int vertical = false;
+ int firstelement = true;
+ os->put_char('(')->inc_indent();
+ vertical = (advanced_length(os) > os->get_max_column() - os->get_column());
+
+ std::for_each(begin(), end(), [&](const std::shared_ptr<sexp_object_t> &obj) {
+ if (!firstelement) {
+ if (vertical)
+ os->new_line(sexp_output_stream_t::advanced);
+ else
+ os->put_char(' ');
+ }
+ obj->print_advanced(os);
+ firstelement = false;
+ });
+
+ if (os->get_max_column() > 0 && os->get_column() > os->get_max_column() - 2)
+ os->new_line(sexp_output_stream_t::advanced);
+ return os->dec_indent()->put_char(')');
+}
+
+/*
+ * sexp_list_t::advanced_length(os)
+ * Returns length of printed image of list given as iterator
+ */
+size_t sexp_list_t::advanced_length(sexp_output_stream_t *os) const
+{
+ size_t len = 1; /* for left paren */
+ std::for_each(begin(), end(), [&](const std::shared_ptr<sexp_object_t> &obj) {
+ len += obj->advanced_length(os);
+ });
+ return (len + 1); /* for final paren */
+}
+
+/*
+ * sexp_object_t::print_advanced(os)
+ * Prints out object on output stream os
+ */
+sexp_output_stream_t *sexp_object_t::print_advanced(sexp_output_stream_t *os) const
+{
+ if (os->get_max_column() > 0 && os->get_column() > os->get_max_column() - 4)
+ os->new_line(sexp_output_stream_t::advanced);
+ return os;
+}
+
+} // namespace sexp \ No newline at end of file
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-output.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-output.cpp
new file mode 100644
index 0000000000..33e42fbba5
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-output.cpp
@@ -0,0 +1,208 @@
+/**
+ *
+ * Copyright (c) 2022-2023, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP implementation code sexp-output.c
+ * Ron Rivest
+ * 5/5/1997
+ */
+
+#include <sexp/sexp.h>
+
+namespace sexp {
+
+static const char *hexDigits = "0123456789ABCDEF";
+static const char *base64Digits =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/*
+ * sexp_output_stream_t::sexp_output_stream_t
+ * Creates and initializes new sexp_output_stream_t object.
+ */
+sexp_output_stream_t::sexp_output_stream_t(std::ostream *o)
+{
+ set_output(o);
+}
+
+/*
+ * sexp_output_stream_t::set_output
+ * Re-initializes new sexp_output_stream_t object.
+ */
+sexp_output_stream_t *sexp_output_stream_t::set_output(std::ostream *o)
+{
+ output_file = o;
+ byte_size = 8;
+ bits = 0;
+ n_bits = 0;
+ mode = canonical;
+ column = 0;
+ max_column = default_line_length;
+ indent = 0;
+ base64_count = 0;
+ return this;
+}
+
+/*
+ * sexp_output_stream_t::put_char(c)
+ * Puts the character c out on the output stream os.
+ * Keeps track of the "column" the next output char will go to.
+ */
+sexp_output_stream_t *sexp_output_stream_t::put_char(int c)
+{
+ output_file->put(c);
+ column++;
+ return this;
+}
+
+/*
+ * sexp_output_stream_t::var_put_char(c)
+ * put_char with variable sized output bytes considered.
+ * int c; -- this is always an eight-bit byte being output
+ */
+sexp_output_stream_t *sexp_output_stream_t::var_put_char(int c)
+{
+ c &= 0xFF;
+ bits = (bits << 8) | c;
+ n_bits += 8;
+ while (n_bits >= byte_size) {
+ if ((byte_size == 6 || byte_size == 4 || c == '}' || c == '{' || c == '#' ||
+ c == '|') &&
+ max_column > 0 && column >= max_column)
+ new_line(mode);
+ if (byte_size == 4)
+ put_char(hexDigits[(bits >> (n_bits - 4)) & 0x0F]);
+ else if (byte_size == 6)
+ put_char(base64Digits[(bits >> (n_bits - 6)) & 0x3F]);
+ else if (byte_size == 8)
+ put_char(bits & 0xFF);
+ n_bits -= byte_size;
+ base64_count++;
+ }
+ return this;
+}
+
+/*
+ * sexp_output_stream_t::change_output_byte_size(newByteSize,newMode)
+ * Change os->byte_size to newByteSize
+ * record mode in output stream for automatic line breaks
+ */
+sexp_output_stream_t *sexp_output_stream_t::change_output_byte_size(int newByteSize,
+ sexp_print_mode newMode)
+{
+ if (newByteSize != 4 && newByteSize != 6 && newByteSize != 8)
+ sexp_error(sexp_exception_t::error, "Illegal output base %d", newByteSize, 0, EOF);
+ if (newByteSize != 8 && byte_size != 8)
+ sexp_error(sexp_exception_t::error,
+ "Illegal change of output byte size from %d to %d",
+ byte_size,
+ newByteSize,
+ EOF);
+ byte_size = newByteSize;
+ n_bits = 0;
+ bits = 0;
+ base64_count = 0;
+ mode = newMode;
+ return this;
+}
+
+/*
+ * sexp_output_stream_t::flush()
+ * flush out any remaining bits
+ */
+sexp_output_stream_t *sexp_output_stream_t::flush(void)
+{
+ if (n_bits > 0) {
+ assert(byte_size == 6);
+ put_char(base64Digits[(bits << (6 - n_bits)) & 0x3F]);
+ n_bits = 0;
+ base64_count++;
+ }
+ if (byte_size == 6) { /* and add switch here */
+ while ((base64_count & 3) != 0) {
+ if (max_column > 0 && column >= max_column)
+ new_line(mode);
+ put_char('=');
+ base64_count++;
+ }
+ }
+ return this;
+}
+
+/*
+ * sexp_output_stream_t::new_line(mode)
+ * Outputs a newline symbol to the output stream os.
+ * For advanced mode, also outputs indentation as one blank per
+ * indentation level (but never indents more than half of max_column).
+ * Resets column for next output character.
+ */
+sexp_output_stream_t *sexp_output_stream_t::new_line(sexp_print_mode mode)
+{
+ if (mode == advanced || mode == base64) {
+ put_char('\n');
+ column = 0;
+ }
+ if (mode == advanced) {
+ for (uint32_t i = 0; i < indent && (4 * i) < max_column; i++)
+ put_char(' ');
+ }
+ return this;
+}
+
+/*
+ * sexp_output_stream_t::print_decimal(n)
+ * print out n in decimal to output stream os
+ */
+sexp_output_stream_t *sexp_output_stream_t::print_decimal(uint64_t n)
+{
+ char buffer[20]; // 64*ln(2)/ln(10)
+ snprintf(buffer,
+ sizeof(buffer) / sizeof(buffer[0]),
+#ifdef _WIN32
+ "%llu",
+#else
+ "%lu",
+#endif
+ n); // since itoa is not a part of any standard
+ for (uint32_t i = 0; buffer[i] != 0; i++)
+ var_put_char(buffer[i]);
+ return this;
+}
+
+/*
+ * base64 MODE
+ * Same as canonical, except all characters get put out as base 64 ones
+ */
+
+sexp_output_stream_t *sexp_output_stream_t::print_base64(
+ const std::shared_ptr<sexp_object_t> &object)
+{
+ change_output_byte_size(8, base64)->var_put_char('{')->change_output_byte_size(6, base64);
+ print_canonical(object);
+ return flush()->change_output_byte_size(8, base64)->var_put_char('}');
+}
+} // namespace sexp
diff --git a/comm/third_party/rnp/src/libsexp/src/sexp-simple-string.cpp b/comm/third_party/rnp/src/libsexp/src/sexp-simple-string.cpp
new file mode 100644
index 0000000000..612ef22705
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/src/sexp-simple-string.cpp
@@ -0,0 +1,197 @@
+/**
+ *
+ * Copyright (c) 2022, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ * This file is a part of RNP sexp library
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original copyright
+ *
+ * SEXP implementation code sexp-output.c
+ * Ron Rivest
+ * 5/5/1997
+ */
+
+#include <sexp/sexp.h>
+
+namespace sexp {
+/*
+ * sexp_simple_string_t::print_canonical_verbatim(os)
+ * Print out simple string on output stream os as verbatim string.
+ */
+sexp_output_stream_t *sexp_simple_string_t::print_canonical_verbatim(
+ sexp_output_stream_t *os) const
+{
+ const octet_t *c = c_str();
+ /* print out len: */
+ os->print_decimal(length())->var_put_char(':');
+ /* print characters in fragment */
+ for (uint32_t i = 0; i < length(); i++)
+ os->var_put_char((int) *c++);
+ return os;
+}
+
+/*
+ * sexp_simple_string_t::advanced_length(os)
+ * Returns length of printed image of s
+ */
+size_t sexp_simple_string_t::advanced_length(sexp_output_stream_t *os) const
+{
+ if (can_print_as_token(os))
+ return advanced_length_token();
+ else if (can_print_as_quoted_string())
+ return advanced_length_quoted();
+ else if (length() <= 4 && os->get_byte_size() == 8)
+ return advanced_length_hexadecimal();
+ else if (os->get_byte_size() == 8)
+ return advanced_length_base64();
+ else
+ return 0; /* an error condition */
+}
+
+/*
+ * sexp_simple_string_t::print_token(os)
+ * Prints out simple string ss as a token (assumes that this is OK).
+ * May run over max-column, but there is no fragmentation allowed...
+ */
+sexp_output_stream_t *sexp_simple_string_t::print_token(sexp_output_stream_t *os) const
+{
+ const octet_t *c = c_str();
+ if (os->get_max_column() > 0 && os->get_column() > (os->get_max_column() - length()))
+ os->new_line(sexp_output_stream_t::advanced);
+ for (uint32_t i = 0; i < length(); i++)
+ os->put_char((int) (*c++));
+ return os;
+}
+
+/*
+ * sexp_simple_string_t::print_base64(os)
+ * Prints out simple string ss as a base64 value.
+ */
+sexp_output_stream_t *sexp_simple_string_t::print_base64(sexp_output_stream_t *os) const
+{
+ const octet_t *c = c_str();
+ os->var_put_char('|')->change_output_byte_size(6, sexp_output_stream_t::advanced);
+ for (uint32_t i = 0; i < length(); i++)
+ os->var_put_char((int) (*c++));
+ return os->flush()
+ ->change_output_byte_size(8, sexp_output_stream_t::advanced)
+ ->var_put_char('|');
+}
+
+/*
+ * sexp_simple_string_t::print_hexadecimal(os)
+ * Prints out simple string as a hexadecimal value.
+ */
+sexp_output_stream_t *sexp_simple_string_t::print_hexadecimal(sexp_output_stream_t *os) const
+{
+ const octet_t *c = c_str();
+ os->put_char('#')->change_output_byte_size(4, sexp_output_stream_t::advanced);
+ for (uint32_t i = 0; i < length(); i++)
+ os->var_put_char((int) (*c++));
+ return os->flush()
+ ->change_output_byte_size(8, sexp_output_stream_t::advanced)
+ ->put_char('#');
+}
+
+/*
+ * sexp_simple_string_t::print_quoted(os)
+ * Prints out simple string ss as a quoted string
+ * This code assumes that all characters are tokenchars and blanks,
+ * so no escape sequences need to be generated.
+ * May run over max-column, but there is no fragmentation allowed...
+ */
+sexp_output_stream_t *sexp_simple_string_t::print_quoted(sexp_output_stream_t *os) const
+{
+ const octet_t *c = c_str();
+ os->put_char('\"');
+ for (uint32_t i = 0; i < length(); i++) {
+ if (os->get_max_column() > 0 && os->get_column() >= os->get_max_column() - 2) {
+ os->put_char('\\')->put_char('\n');
+ os->reset_column();
+ }
+ os->put_char(*c++);
+ }
+ return os->put_char('\"');
+}
+
+/*
+ * sexp_simple_string_t::print_advanced(os)
+ * Prints out simple string onto output stream ss
+ */
+sexp_output_stream_t *sexp_simple_string_t::print_advanced(sexp_output_stream_t *os) const
+{
+ if (can_print_as_token(os))
+ print_token(os);
+ else if (can_print_as_quoted_string())
+ print_quoted(os);
+ else if (length() <= 4 && os->get_byte_size() == 8)
+ print_hexadecimal(os);
+ else if (os->get_byte_size() == 8)
+ print_base64(os);
+ else
+ sexp_error(sexp_exception_t::error,
+ "Can't print in advanced mode with restricted output character set",
+ 0,
+ 0,
+ EOF);
+ return os;
+}
+
+/*
+ * sexp_simple_string_t::can_print_as_quoted_string(void)
+ * Returns true if simple string can be printed as a quoted string.
+ * Must have only tokenchars and blanks.
+ */
+bool sexp_simple_string_t::can_print_as_quoted_string(void) const
+{
+ const octet_t *c = c_str();
+ for (uint32_t i = 0; i < length(); i++, c++) {
+ if (!is_token_char((int) (*c)) && *c != ' ')
+ return false;
+ }
+ return true;
+}
+
+/*
+ * sexp_simple_string_t::can_print_as_token(os)
+ * Returns true if simple string can be printed as a token.
+ * Doesn't begin with a digit, and all characters are tokenchars.
+ */
+bool sexp_simple_string_t::can_print_as_token(const sexp_output_stream_t *os) const
+{
+ const octet_t *c = c_str();
+ if (length() <= 0)
+ return false;
+ if (is_dec_digit((int) *c))
+ return false;
+ if (os->get_max_column() > 0 && os->get_column() + length() >= os->get_max_column())
+ return false;
+ for (uint32_t i = 0; i < length(); i++) {
+ if (!is_token_char((int) (*c++)))
+ return false;
+ }
+ return true;
+}
+
+} // namespace sexp
diff --git a/comm/third_party/rnp/src/libsexp/version.txt b/comm/third_party/rnp/src/libsexp/version.txt
new file mode 100644
index 0000000000..100435be13
--- /dev/null
+++ b/comm/third_party/rnp/src/libsexp/version.txt
@@ -0,0 +1 @@
+0.8.2