1. Build system
1.1. Overview
The SST build system is built on top of the GNU Autotools. Before you can start using the build system, you need to identify which package format of SST you’re working with. SST is generally available in three slightly different package formats:
-
The source repository. This repository is only available internally within Stealth. The other package formats are generally derived from this one.
-
A distribution repository. The primary public distribution repository for SST is available at https://github.com/stealthsoftwareinc/sst. You may also have access to other distribution repositories that Stealth has created for private distribution purposes.
-
A distribution archive.
To identify which package format you’re working with, use the following algorithm:
-
If you started with an archive file like
sst-<version>.tar.gzand it extracts to a directory that includes a file namedMakefile.in, then you’re working with a distribution archive.ImportantIf the extracted directory does not include a file named
Makefile.in, then you may have mistakenly downloaded a source archive. This is what you will typically get if you use a download button when viewing the source repository in a repository manager like GitHub or GitLab. SST does not support being built from a source archive.Note that this only applies to download buttons for the source repository, not for a distribution repository. Using a download button on a distribution repository will generally yield a valid distribution archive.
-
Otherwise, if the version control repository includes a file named
Makefile.inin the root directory, then you’re working with a distribution repository. -
Otherwise, you’re working with the source repository.
Once you know which package format you’re working with, using the build system consists of three main steps:
-
Initializing the build system.
-
Configuring the build system.
-
Running the build system.
If you’re working with the source repository, you need to perform steps 1, 2, and 3. Otherwise, you only need to perform steps 2 and 3. Step 1 is only designed to work on modern Linux systems with a variety of tools installed, but steps 2 and 3 are designed to work on a variety of Unix-like systems with minimal tools installed. The idea is that developers work with the source repository and produce distribution archives and distribution repositories for general use.
1.2. Initializing the build system
Initializing the build system
is performed with the ./autogen command.
1.3. Configuring the build system
Configuring the build system
is performed with the ./configure command.
1.3.1. Build groups
Sometimes you might only be interested in building certain parts of SST,
not all of it.
For example, if you’re using SST in a C project, you might only be
interested in building the C library.
To provide control over this, both the
./configure script and the
install/* scripts support the --with-build-groups option, whose
syntax is as follows:
--with-build-groups=[[+|-]<group>[,[+|-]<group>]...]
Each <group> in the comma-separated list specifies some part of the
build system that should be enabled or disabled.
The group will be enabled if the ‘```' prefix is given, or disabled
if the '```-```' prefix is given.
Omitting the prefix is the same as giving the '```’ prefix.
All groups begin as disabled, and the entries of the list will be
applied in order.
If the --with-build-groups option is omitted, the behavior is as if it
had been given as --with-build-groups=default, i.e., the default set
of build groups will be enabled.
Enabling or disabling certain build groups may implicitly enable or
disable other build groups depending on how they are related.
The build groups are as follows:
default-
The default set of build groups:
bash,c,cpp, andjava. bash-
The Bash library.
cc-autotools-
The C library as built and installed by Autotools. When disabled, also disables the
cpp-autotoolsbuild group. cppcpp-autotools-
The C++ library as built and installed by Autotools. When enabled, also enables the
c-autotoolsbuild group. javajava-gatbps-
The Java library as built and installed by GATBPS. When disabled, also disables the
java-mavenbuild group. java-maven-
The Java library as built and installed by Maven.
1.4. Running the build system
Running the build system
is performed with the make command.
1.5. Makefile target reference
manual-
Forwards to the
manual-xztarget. manual-xz-
Builds
doc/sst-0.40.3-manual.tar.xz.Note that this file is subject to
DISTCUT. In other words, it is included prebuilt in all distribution repositories and distribution archives, and its outgoing edges in the make graph are cut so that it will always be considered up to date. To leave the edges uncut, use./configure DISTCUT=ormake DISTCUT=. src/rpm/centos-7/out-
Builds the CentOS 7 RPM package. The
src/rpm/centos-7/outdirectory will be produced, containing several.rpmfiles.Example 1.$ make src/rpm/centos-7/out && echo ok … ok $ tree src/rpm/centos-7/out src/rpm/centos-7/out |-- sst-sst-0.16.1-0.1.gc3e38cc91.el7.src.rpm |-- sst-sst-0.16.1-0.1.gc3e38cc91.el7.x86_64.rpm `-- sst-sst-debuginfo-0.16.1-0.1.gc3e38cc91.el7.x86_64.rpm src/rpm/rhel-7/out-
Builds the RHEL 7 RPM package. The
src/rpm/rhel-7/outdirectory will be produced, containing several.rpmfiles.Example 2.$ make src/rpm/rhel-7/out && echo ok … ok $ tree src/rpm/rhel-7/out src/rpm/rhel-7/out |-- sst-sst-0.16.1-0.1.gc3e38cc91.el7_9.src.rpm |-- sst-sst-0.16.1-0.1.gc3e38cc91.el7_9.x86_64.rpm `-- sst-sst-debuginfo-0.16.1-0.1.gc3e38cc91.el7_9.x86_64.rpm
1.6. Building with Maven
When the java-maven build group is enabled, Maven can be used after
running ./configure.
However, you should run make maven-prep before every mvn command.
2. Bash library
2.1. Including the library
-
#! /bin/sh - set -e || exit $? . sst.bash -
#! /bin/sh - set -e || exit $? if test -f sst.bash; then . ./sst.bash else . sst.bash fi -
#! /bin/sh - case $0 in /*) x=$0 ;; *) x=./$0 esac r='\(.*/\)' x=`expr "x$x" : "x$r"`. || exit $? set -e || exit $? . "$x/sst/sst.bash"
For repository scripts:
#-----------------------------------------------------------------------
# Include the SST Bash library
#-----------------------------------------------------------------------
#
# Include the first sst.bash file found by searching up the directory
# tree starting from the location of this script file. If no such file
# is found, fall back to including plain sst.bash with PATH resolution.
#
# This section is written in portable shell to ensure it works properly
# in any shell.
#
case ${SST_SEARCH_UP_X-} in '')
case $0 in /*)
SST_SEARCH_UP_X=$0
;; *)
SST_SEARCH_UP_X=./$0
esac
SST_SEARCH_UP_R='\(.*/\)'
SST_SEARCH_UP_X=`
expr "x${SST_SEARCH_UP_X?}" : "x${SST_SEARCH_UP_R?}"
`. || exit $?
unset SST_SEARCH_UP_R
SST_SEARCH_UP_X=`
cd "${SST_SEARCH_UP_X?}" || exit $?
while :; do
if test -f sst.bash; then
case ${PWD?} in *[!/\]*)
printf '%s\n' "${PWD?}"/ || exit $?
;; *)
printf '%s\n' "${PWD?}" || exit $?
esac
exit
fi
case ${PWD?} in *[!/\]*)
cd ..
;; *)
exit
esac
done
` || exit $?
export SST_SEARCH_UP_X
esac
set -e || exit $?
. "${SST_SEARCH_UP_X?}"sst.bash
unset SST_SEARCH_UP_X
2.2. Bootstrapping
The SST Bash library prelude runs the following bootstrap clause before running any Bash-specific code that may not be portable to other shells:
case ${SST_BASH_BOOTSTRAP+x}y$# in
y0) SST_BASH_BOOTSTRAP= exec bash - "$0" ;;
y*) SST_BASH_BOOTSTRAP= exec bash - "$0" "$@" ;;
esac
unset SST_BASH_BOOTSTRAP
This clause re-executes the script with the PATH-resolved bash.
There are two reasons for doing this.
First, if the script uses a /bin/bash shebang on a system where the
PATH-resolved bash is newer than /bin/bash (e.g., on macOS), then
the script will be re-executed with the newer version.
Second, since this code is portable enough to run in any shell, a script
can actually use a /bin/sh shebang, which is the most portable shell
shebang, and still get bootstrapped into the PATH-resolved bash.
The unset command prevents other scripts from being tricked into
believing they’ve already bootstrapped.
2.3. Reserved identifiers
The SST Bash library reserves all identifiers beginning with sst_ or
SST_ in both the variable namespace and the function namespace.
2.4. Postmortem job containers
As part of its EXIT trap, the prelude includes opt-in code that can detect whether the script is running in a CI job container, and if so, commit and push the container to a registry for later inspection. Such a container is called a postmortem job container.
The code behaves as follows:
-
If the script is not running in a CI job, stop.
-
If the script is being called by another script that uses the SST Bash library, stop.
This means that, in a call stack that includes multiple scripts that use the SST Bash library, only the outermost such script will possibly push the postmortem job container.
-
If the
SST_PUSH_POSTMORTEM_JOB_CONTAINERenvironment variable is unset or empty, stop.You must set the
SST_PUSH_POSTMORTEM_JOB_CONTAINERenvironment variable to a nonempty value to opt in. If you leave it unset or empty, postmortem job containers will never be pushed. -
If the
SST_NO_PUSH_POSTMORTEM_JOB_CONTAINERenvironment variable is nonempty, stop.You can set the
SST_NO_PUSH_POSTMORTEM_JOB_CONTAINERenvironment variable to a nonempty value to opt out regardless of any opting in. -
If the script is running in a GitLab CI job:
-
If the job is protected and the
SST_PUSH_PROTECTED_POSTMORTEM_JOB_CONTAINERis unset or empty, stop.You must set the
SST_PUSH_PROTECTED_POSTMORTEM_JOB_CONTAINERenvironment variable to a nonempty value to opt in for protected jobs. If you leave it unset or empty, postmortem job containers will never be pushed for protected jobs.
-
2.5. General development guidelines
This section provides guidelines for using the SST Bash library and writing Bash code in general.
The minimum version of Bash supported by the SST Bash library is Bash 4.1. However, development work is typically done on a system with a newer version of Bash. This makes it easy to accidentally introduce subtle dependencies on the newer version, which you may want to avoid depending on the constraints of your project. This section provides a set of guidelines that you can follow to reduce problems when aiming to support Bash 4.1.
2.5.1. Do not make global variables readonly
When a global variable is made readonly, it cannot be shadowed by
a local variable in a function.
a.bashset -e || exit $?
. src/bash/sst.bash
w=hello
readonly w
echo $w
function g {
local w
w=world
readonly w
echo $w
}; readonly -f g
g
hello
a.bash: line 9: local: w: readonly variable
a.bash: error: command exited with status 1: local w
at g(a.bash:12)
at main(a.bash:15)
This can generally be avoided by preferring to put code into functions
and using local variables.
a.bashset -e || exit $?
. src/bash/sst.bash
function f {
local w
w=hello
readonly w
echo $w
}; readonly -f f
function g {
local w
w=world
readonly w
f
echo $w
}; readonly -f g
g
hello world
2.5.2. Do not make IFS readonly
As an important special case of
Section 2.5.1, do not make IFS
readonly.
2.5.3. Global variable declarations
Bash <4.2 does not support declare -g in functions.
Ignoring shadowing problems, global variable declarations can always be
safely omitted except when a function needs to use a global associative
array that may not have been declared yet.
In this case, instead of writing declare -g -A foo in the function,
write declare -A foo in the global scope just before the function.
For stylistic reasons, you may want to put commented-out
# Bash >=4.2: declare -g declarations in a function for all global
variables used by the function regardless of whether the declarations
would technically be necessary.
These declarations are helpful to the reader, and you can enable them
later if you eventually migrate to Bash >=4.2.
|
Warning
|
If you’re working on the SST Bash library itself, do not put any global
variable declarations at the top of any function file.
Although that area looks like it’s the global scope, it actually isn’t,
as the library’s automatic function loading mechanism loads function
files in function scope.
Instead, add a commented-out |
2.5.4. Always use x="$@" to collect the positional parameters separated by spaces
Some versions of Bash sometimes have incorrect behavior for x=$* and
x=$@, while x="$@" always works:
$ cat a.bash
set -e -u -o pipefail
for v in 4.{1,2,3,4} 5.{0,1}; do
docker run -i -t --rm bash:$v bash --version | awk 'NR == 1'
for rhs in '$*' '$@' '"$*"' '"$@"'; do
printf ' %7s ' "x=$rhs:"
docker run -i -t --rm bash:$v bash -c '
set " "
unset IFS
x='"$rhs"'
printf "[%s]\\n" "$x"
'
done
done
$ bash a.bash
GNU bash, version 4.1.17(2)-release (x86_64-pc-linux-musl)
x=$*: [ ]
x=$@: []
x="$*": [ ]
x="$@": [ ]
GNU bash, version 4.2.53(2)-release (x86_64-pc-linux-musl)
x=$*: [ ]
x=$@: []
x="$*": [ ]
x="$@": [ ]
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-musl)
x=$*: []
x=$@: [ ]
x="$*": [ ]
x="$@": [ ]
GNU bash, version 4.4.23(1)-release (x86_64-pc-linux-musl)
x=$*: []
x=$@: [ ]
x="$*": [ ]
x="$@": [ ]
GNU bash, version 5.0.18(1)-release (x86_64-pc-linux-musl)
x=$*: [ ]
x=$@: [ ]
x="$*": [ ]
x="$@": [ ]
GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-musl)
x=$*: [ ]
x=$@: [ ]
x="$*": [ ]
x="$@": [ ]
Note that x="$*" also always works, but x="$@" is still preferred
when space separation is desired, as it is not affected by IFS.
2.6. Internal development guidelines
This section provides guidelines for working on the SST Bash library itself.
2.7. Core functions
2.7.1. The sst_nl function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_nl
The sst_nl function copies the content of standard input to standard
output, appending a newline character to the end if not already present.
2.7.2. The sst_csf function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_csf [<&var>]...
If no arguments are given, the sst_csf function copies the content of
standard input to standard output, appending an “x” character and
a newline character.
Otherwise, the function removes the last character from each <&var> if
it exists as an “x” character, and removes the next last character
if it exists as a newline character.
The purpose of the sst_csf function is to allow command substitutions
to be used that only remove a single trailing newline character instead
of as many trailing newline characters as possible.
To be more specific, instead of writing foo=$(bar), you can write
foo=$(bar | sst_csf); sst_csf foo.
The “csf” abbreviation in the function name is short for “command substitution fix”.
When input is said to be read in sst_csf form, it means that the
input is taken to be all characters up to but not including a possible
single trailing newline character.
When output is said to be written in sst_csf form, it means that
the output is followed by a single trailing newline character.
2.7.3. The sst_ihd function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ihd [<n>]
The sst_ihd function copies the content of standard input to standard
output, removing <n> space characters from the beginning of each line.
Lines that do not begin with <n> space characters are left unchanged.
If all lines are empty, all lines are left unchanged.
Otherwise, if <n> is omitted, it is taken to be the length \(k\) of
the longest possible sequence of space characters at the beginning of
the first nonempty line, which may be zero.
Otherwise, if <n> is negative, it is adjusted to
\(\max\left(k + \mathtt{<n>}, 0\right)\).
If the input is empty, the output will be empty. Otherwise, a trailing newline character will be appended to the last line of output if not already present.
The “ihd” abbreviation in the function name is short for “indented here-document”.
2.7.4. The sst_ihs function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ihs [<n>]
The sst_ihs function is equivalent to the sst_ihd function
except the first and last lines of input are ignored.
The “ihs” abbreviation in the function name is short for “indented here-string”.
2.7.5. The sst_join function
sst_join [<arg>...]
The sst_join function writes the space-separated concatenation of the
arguments to standard output in [bl_sst_csf] form.
If no arguments are given, the concatenation is the empty string.
2.7.6. The sst_quote function
The sst_quote function converts the input into a portably quoted
shell word.
The algorithm is as follows:
-
Replace every
'character with'\''. -
Prepend a
'character to the entire result. -
Append a
'character to the entire result.
2.7.7. The sst_quote_list function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_quote_list [<argument>...]
The sst_quote_list function converts each <argument> to a
portably quoted shell word and outputs the resulting list of words,
separated by space characters.
If no <argument>s are given, the output is empty.
Each conversion is performed using the same algorithm as the
sst_quote function.
The output is written to standard output in CSF form.
2.7.8. The sst_smart_quote function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_smart_quote [<arg>]...
The sst_smart_quote function is equivalent to the sst_quote
function except that if the result matches the regular expression
^'[+./0-9:=A-Z_a-z-]+'$,
the quotes are removed.
2.7.9. The sst_regex_escape function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_regex_escape [<arg>]...
The sst_regex_escape function escapes the input for use in a
Bash regular expression.
2.7.10. The sst_regex_escape_list function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_regex_escape_list [<arg>]...
The sst_regex_escape_list function outputs a
Bash regular expression that matches any of the arguments.
If no arguments are given, the regular expression will never match.
The regular expression is always parenthesized.
The output is written to standard output in CSF form.
2.7.11. The sst_barf function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_barf [<arg>]…
The sst_barf function prints an error message and a stack trace
to standard error and terminates the script.
The error message consists of the string "$0: Error: ", followed by
the space-separated concatenation of the arguments, followed by a
newline character.
If the SST_BARF_STATUS variable is set to an integer between 0 and 255
inclusive, the exit status will be $SST_BARF_STATUS.
Otherwise, if sst_barf was called implicitly by a failed command,
the exit status will be that of the failed command.
Otherwise, the exit status will be 1.
2.7.12. The sst_warn function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_warn [<arg>]…
The sst_warn function prints a warning message to standard error.
The warning message consists of the string "$0: warning: ", followed
by the space-separated concatenation of the arguments, followed by a
newline character.
2.7.13. The sst_info function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_info [<arg>]…
The sst_info function prints an informative message to standard
output.
The informative message consists of the string "$0: ", followed by the
space-separated concatenation of the arguments, followed by a newline
character.
2.7.14. The sst_unimplemented function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_unimplemented
2.7.15. The sst_expect_not_subshell function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_not_subshell [<function>]
The sst_expect_not_subshell function verifies that the current
code is not running in a subshell[1].
If the verification fails, sst_barf will be called with an
appropriate error message.
The error message will state that <function> must not be called in a
subshell.
If <function> is omitted, it is inferred as the name of the calling
function.
If <function> is a single “-” character, the error message will
instead generically state that the current code must not be run in a
subshell.
#! /bin/sh -
set -e || exit $?
. sst.bash
function foo {
sst_expect_not_subshell "$@"
}
foo # ok
(foo) # error stating that foo must not be called in a subshell
(foo bar) # error stating that bar must not be called in a subshell
(foo -) # error stating that no subshell was expected
2.7.16. The sst_push_var function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_push_var <&var> [<value>]
The sst_push_var function saves the current value of <&var>
onto a stack and sets <&var> to <value>.
The most recent saved value of <&var> can be restored by calling
sst_pop_var.
If <&var> is currently unset, its unset-ness will be saved onto the
stack, and the corresponding call to sst_pop_var will unset
<&var>.
If <value> is omitted, <&var> will be unset instead of being set
to <value>.
2.7.17. The sst_pop_var function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_pop_var <&var>
2.7.18. The sst_set_exit function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_set_exit [<status>]
The sst_set_exit function takes no action and returns with exit
status <status>.
If <status> is omitted, it is taken to be the exit status of the last
command executed, in which case the call is effectively a noop.
2.7.19. The sst_expect_exit_status function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_exit_status [<argument>]...
The sst_expect_exit_status function verifies that each
<argument> is an exit status.
A string is an exit status if all of the following are true:
-
The string matches the regular expression
/^(0|[1-9][0-9]{0,2})$/. -
The integer value represented by the string is between 0 and 255.
2.8. Array functions
2.8.1. The sst_array_cmp function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_array_cmp <array1> <array2>
The sst_array_cmp function compares two arrays.
The arrays are compared in lexical order first on their keys, and then
on their values.
The result is -1, 0, or 1.
The result is printed to standard output in [bl_sst_csf] form.
|
Warning
|
This function currently does not work properly when either of the arrays is an associative array. This is planned to be fixed in the future. |
2.8.2. The sst_array_to_string function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_array_to_string <array>
The sst_array_to_string function converts an array to a string.
The output is written to standard output in [bl_sst_csf] form.
2.8.3. The sst_array_from_zterm function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_array_from_zterm <array> [<command> [<arg>]…]
The sst_array_from_zterm function parses a sequence of
zero-terminated elements into <array>.
If <command> [<arg>]… is given, it is run with standard input as its
standard input and the elements are parsed from its standard output.
Otherwise, the elements are parsed from standard input.
If the element sequence is empty, the resulting array will be empty. Otherwise, the zero terminator of the last element is optional if the last element is nonempty.
|
Warning
|
Using For example, in
|
sst_array_from_zterm xs printf '' # xs=()
sst_array_from_zterm xs printf '\0' # xs=('')
sst_array_from_zterm xs printf 'a' # xs=('a')
sst_array_from_zterm xs printf 'a\0' # xs=('a')
sst_array_from_zterm xs printf '\0\0' # xs=('' '')
sst_array_from_zterm xs printf 'a\0\0' # xs=('a' '')
sst_array_from_zterm xs printf 'a\0b' # xs=('a' 'b')
sst_array_from_zterm xs printf 'a\0b\0' # xs=('a' 'b')
2.9. Path functions
2.9.1. The sst_abs_dir function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_abs_dir [<path>]
The sst_abs_dir function outputs an absolute path to <path>
that includes a trailing / character.
<path> is not validated against the file system and need not exist.
If <path> is empty, sst_barf will be called.
The output is guaranteed to begin and end with a / character.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
This function is equivalent to calling sst_add_slash followed by
sst_abs_prefix followed by sst_squish_slashes, except it
may have improved performance.
2.9.2. The sst_abs_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_abs_file [<path>]
The sst_abs_file function outputs an absolute path to <path>.
<path> is not validated against the file system and need not exist.
sst_barf will be called if any of the following is true:
-
<path>is empty. -
<path>is.. -
<path>is... -
<path>ends with/. -
<path>ends with/.. -
<path>ends with/...
The output is guaranteed to begin with a / character.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
This function is equivalent to calling sst_abs_dir followed by
sst_trim_slashes, except it may have improved performance and
inputs that cannot possibly be file paths are rejected.
2.9.3. The sst_abs_prefix function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_abs_prefix [<path>]
The sst_abs_prefix function constructs an absolute path to
<path>, removes any characters after the last / character, and
outputs the result.
<path> is not validated against the file system and need not exist.
If <path> ends with a / character, the behavior is as if it ended
with /. instead.
If <path> is empty, sst_barf will be called.
The output is guaranteed to begin and end with a / character.
The output is guaranteed to be free of . and .. components if any of
the following is true:
-
<path>is free of.and..components. -
<path>ends with/.but is otherwise free of.and..components. -
<path>is a.character.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.9.4. The sst_add_slash function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_add_slash [<path>]
The sst_add_slash function appends a / character to <path> if
<path> ends with a non-/ character.
If <path> is empty, sst_barf will be called.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.9.5. The sst_add_slash_abs_prefix function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_add_slash_abs_prefix [<path>]
The sst_add_slash_abs_prefix function is equivalent to calling
sst_add_slash followed by sst_abs_prefix, except it may
have improved performance.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.9.6. The sst_add_slash_dot_slash function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_add_slash_dot_slash [<path>]
The sst_add_slash_dot_slash function is equivalent to calling
sst_add_slash followed by sst_dot_slash, except it may
have improved performance.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.9.7. The sst_dot_slash function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_dot_slash [<path>]
The sst_dot_slash function prepends ./ to <path> if <path>
does not begin with / or ./.
If <path> is empty, sst_barf will be called.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function is primarily used to adjust an arbitrary path to be safe
to use as a program argument.
Without adjustment, an unusual path like --foo may be mistakenly
interpreted as an option instead of an operand.
For example, rm --foo will fail, but rm ./--foo will work.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
path=$(sst_dot_slash "$path" | [bl_sst_csf])
[bl_sst_csf] path
sst_dot_slash / # /\n
sst_dot_slash /foo # /foo\n
sst_dot_slash '' # \n
sst_dot_slash foo # ./foo\n
sst_dot_slash -foo # ./-foo\n
sst_dot_slash --foo # ./--foo\n
printf 'foo\n:' | sst_dot_slash # ./foo\n:\n
printf 'foo\n:\n' | sst_dot_slash # ./foo\n:\n
printf 'foo\n:\n\n' | sst_dot_slash # ./foo\n:\n\n
2.9.8. The sst_expect_prefix function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_prefix [<path>]
The sst_expect_prefix function is equivalent to the
sst_get_prefix function except it also verifies that the
output is nonempty.
2.9.9. The sst_get_prefix function
sst_get_prefix [<path>]
The sst_get_prefix function gets the longest initial substring of
<path> that ends in a / character.
If <path> does not contain a / character, the result is the empty
string.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
sst_get_prefix foo # \n
sst_get_prefix foo/ # foo/\n
sst_get_prefix foo/bar # foo/\n
sst_get_prefix foo/bar/ # foo/bar/\n
sst_get_prefix foo/bar/baz # foo/bar/\n
2.9.10. The sst_safe_dir function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_safe_dir [<path>]
The sst_safe_dir function outputs a path to <path> that
includes a trailing / character.
<path> is not validated against the file system and need not exist.
If <path> is empty, sst_barf will be called.
The output is guaranteed to begin with a / or . character and end
with a / character.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function never requires the use of sst_csf, as the output
never ends with a newline character (before it is written to standard
output in CSF form).
In other words, a plain command substitution always correctly
collects the output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
This function is equivalent to calling sst_add_slash followed by
sst_dot_slash followed by sst_squish_slashes, except it
may have improved performance.
2.9.11. The sst_safe_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_safe_file [<path>]
The sst_safe_file function outputs an adjusted path to <path>.
<path> is not validated against the file system and need not exist.
sst_barf will be called if any of the following is true:
-
<path>is empty. -
<path>is.. -
<path>is... -
<path>ends with/. -
<path>ends with/.. -
<path>ends with/...
The output is guaranteed to begin with a / or . character.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
This function is equivalent to calling sst_safe_dir followed by
sst_trim_slashes, except it may have improved performance and
inputs that cannot possibly be file paths are rejected.
2.9.12. The sst_squish_slashes function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_squish_slashes [<path>]
The sst_squish_slashes function replaces each maximal sequence of
/ characters in <path> with a single / character, subject to the
following exceptions:
-
If
<path>is exactly//, the output will be exactly//. -
If
<path>begins with//followed by a non-/character, the initial//will be preserved.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.9.13. The sst_trim_slashes function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_trim_slashes [<path>]
The sst_trim_slashes function removes all trailing / characters
from <path>, subject to the following exceptions:
-
If
<path>is/, the output will be/. -
If
<path>is//, the output will be//. -
If
<path>begins with///and consists entirely of/characters, the output will be/.
If <path> is not given, the input is read from standard
input in CSF form.
The output is always written to standard output in CSF form.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.10. JSON functions
2.10.1. The sst_json_escape function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_json_escape [<text>]...
The sst_json_escape function escapes the input to be suitable to
use in a JSON string.
The input is the space-separated concatenation of the arguments. If no arguments are given, the input is read from standard input in CSF form instead. The output is always written to standard output in CSF form.
The input must be encoded with UTF-8.
If the input contains an invalid sequence of UTF-8 code units,
sst_barf is called.
The output is encoded with UTF-8 and always consists of code points
between U+0020 and U+007E.
Any code point outside this range is always represented as \b, \f,
\n, \r, \t, \uXXXX, or a UTF-16 surrogate pair \uXXXX\uXXXX.
It is unspecified which representation is used for any occurrence of any
code point that can be represented more than one way, including even for
code points between U+0020 and U+007E.
2.10.2. The sst_json_quote function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_json_quote [<text>]...
The sst_json_quote function quotes the input as a JSON string.
The input is the space-separated concatenation of the arguments. If no arguments are given, the input is read from standard input in CSF form instead. The output is always written to standard output in CSF form.
The input must be encoded with UTF-8.
If the input contains an invalid sequence of UTF-8 code units,
sst_barf is called.
The output is encoded with UTF-8 and always consists of code points
between U+0020 and U+007E.
Any code point outside this range is always represented as \b, \f,
\n, \r, \t, \uXXXX, or a UTF-16 surrogate pair \uXXXX\uXXXX.
It is unspecified which representation is used for any occurrence of any
code point that can be represented more than one way, including even for
code points between U+0020 and U+007E.
2.10.3. The sst_jq_expect function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_jq_expect <condition> [<format> [<arg>...]]
The sst_jq_expect function checks a condition on JSON input using the
jq utility and terminates the script if the condition is false.
The JSON input is read from standard input.
The <condition> argument specifies the condition to check.
It should be a jq filter that outputs true or false.
If the condition is true, no action is taken.
Otherwise, the script is terminated by calling
[bl_sst_barf] [<format> [<arg>…]].
2.10.4. The sst_jq_get_string function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_jq_get_string <json> [<filter>] <&var>
The sst_jq_get_string function uses the jq utility to parse a JSON
string into a variable.
<json> specifies the JSON value on which to run jq.
If <json> is a single - character, the JSON value is
read from standard input.
Otherwise, if <json> begins with a /, A-Z, a-z,
0-9, ., _, or - character, it is taken to be a path to a file
from which to read the JSON value.
Otherwise, <json> is taken literally as the JSON value.
If the input is actually a sequence of JSON values, all but the first
JSON value is ignored.
<filter> specifies the jq filter to run on <json>.
The filter should produce either a null value or a string value.
A null value will be implicitly adjusted to an empty string value.
If <filter> is omitted, it is taken to be .<&var>.
The resulting string value is assigned to <&var>.
2.10.5. The sst_jq_get_strings function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_jq_get_strings <json> <filter> <var>
The sst_jq_get_strings function parses an array of JSON strings into
an indexed array.
<json> specifies the JSON value on which to run jq.
If <json> is a single - character, the JSON value is
read from standard input.
Otherwise, if <json> begins with a /, A-Z, a-z,
0-9, ., _, or - character, it is taken to be a path to a file
from which to read the JSON value.
Otherwise, <json> is taken literally as the JSON value.
If the input is actually a sequence of JSON values, all but the first
JSON value is ignored.
<filter> specifies the jq filter to run on <json>.
The filter should produce either a single null value, a single string
value, or an array of null and string values.
A single value is implicitly adjusted to an array containing that value,
an empty array is implicitly adjusted to an array containing an empty
string value, and each null value is implicitly adjusted to an empty
string value.
The resulting JSON array is parsed into the variable named <var> as an
indexed array.
2.11. Command-line argument parsing
2.11.1. The sst_parse_opt function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_parse_opt [<prefix=>] (<option>... | <matcher>())
[<style=required>] (: "$@" | :<&array>[:<i=0>])
The sst_parse_opt function attempts to parse an option from the
beginning of a list of command-line arguments.
When sst_parse_opt returns, the following variables will have
been updated in the calling context:
<prefix>got-
A boolean value indicating whether an option was parsed.
<prefix>opt-
The option that was parsed, or unset if an option was not parsed.
<prefix>arg-
The option argument that was parsed, or unset if an option argument was not parsed.
<prefix>pop-
A code fragment that you should execute with
evalimmediately after thesst_parse_optcall returns. If an option was parsed, the code fragment will remove the option from the list of command-line arguments so thatsst_parse_optmay be called again to attempt to parse another option. Otherwise, the code fragment will do nothing.
2.11.2. The sst_unknown_opt function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_unknown_opt <arg>
2.12. Unit testing
2.12.1. The sst_test function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_test [<status=0>[(:|=)<output=>]] <code> [<checks> [<show>]...]
2.13. Build system functions
2.13.1. The build-dist-archive.bash script
build-dist-archive.bash
[--build-depends=<package>]...
The build-dist-archive.bash script builds the
distribution archive of an Autotools project.
--build-depends=<package>-
Specifies that
<package>should be installed before running./configure. This option can be specified multiple times to install multiple packages.
2.13.2. The sst_ag_call_defun_once_macros function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ag_call_defun_once_macros
2.13.3. The sst_ag_define_ordering_macros function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ag_define_ordering_macros
The sst_ag_define_ordering_macros function generates every
nonexistent macro \(y\) implied by the existence of a
GATBPS_BEFORE([$0], [\(y\)]) call.
Each \(y\) is called an ordering macro.
Consider the set of all pairs \((x, y)\) implied by the existence of
any GATBPS_BEFORE([$0], [\(y\)]) call in any macro \(x\) defined
in m4/\(x\).m4.
For each unique \(y\) for which m4/\(y\).m4 does not exist,
m4/\(y\).m4 will be generated, defining \(y\) to call
GATBPS_REQUIRE([\(x\)]) for every corresponding \(x\).
2.13.4. The sst_ag_include function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ag_include [<file>...]
2.13.5. The sst_ag_process_leaf function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ag_process_leaf <target> <leaf> <&child>
2.13.6. The sst_ac_include function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ac_include [<file>...]
2.13.7. The sst_ac_config_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ac_config_file [<file>...]
2.13.8. The sst_am_include function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_include [<file>...]
2.13.9. The sst_am_distribute function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_distribute [<path>]...
The sst_am_distribute function adds each <path> to the distributed
files list.
<path> must either exist as a file, exist as a directory, or not
exist.
A repeated <path> will be skipped, even across multiple calls.
This function must not be called from a subshell.
2.13.10. The sst_am_distribute_if_not_dir function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_distribute_if_not_dir [<path>]...
The sst_am_distribute_if_not_dir function adds each <path> to the
distributed files list, but skips <path> if it exists as a directory.
<path> must either exist as a file, exist as a directory, or not
exist.
A repeated <path> will be skipped, even across multiple calls.
This function must not be called from a subshell.
2.13.11. The sst_am_var_set function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_var_set <var> [<arg>]...
2.13.12. The sst_am_var_set_const function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_var_set_const <var> [<arg>]...
2.13.13. The sst_am_var_add function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_var_add <var> [<arg>]...
2.13.14. The sst_am_var_add_unique_word function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_var_add_unique_word <var> [<word>...]
2.13.15. The sst_am_var_add_unique_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_var_add_unique_file <var> [<file>...]
2.13.16. The sst_am_if function
The sst_am_if function starts an if block for the
AM_CONDITIONAL variable <var>.
If the ! character is given, the condition will be negated.
The block must be ended by a matching call to sst_am_elif,
sst_am_else, or sst_am_endif.
2.13.17. The sst_am_elif function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_elif <var> [<expected_comment>]
2.13.18. The sst_am_else function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_else [<expected_comment>]
2.13.19. The sst_am_endif function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_am_endif [<expected_comment>]
The sst_am_endif function ends the if block started
by the matching call to sst_am_if, sst_am_elif, or
sst_am_else.
If <expected_comment> is given, it will be verified to match the
condition of the block being ended.
2.14. Miscellaneous
2.14.1. The sst_libdir variable
The sst_libdir variable provides an absolute path to the
directory that contains the SST Bash library.
The path is guaranteed to begin with a / character and end with a
non-/ character.
#! /bin/sh -
set -e || exit $?
. sst.bash
printf '%s\n' "$sst_libdir"
/usr/local/share/sst/bash
2.14.2. The sst_is0atty variable
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_is0atty=<boolean>
The sst_is0atty variable indicates whether standard input is connected
to a terminal.
sst_is0atty=<boolean> means that sst_is0atty is set to either
1 or null to indicate true or false, respectively.
Because arithmetic evaluation implicitly converts null variables to
0, this means that sst_is0atty can be compared to true with either
[[ "$sst_is0atty" ]] or ((sst_is0atty)), and compared to
false with either [[ ! "$sst_is0atty" ]] or
((!sst_is0atty)).
docker run --rm -i ${sst_is0atty:+-t} ubuntu echo hello world
2.14.3. The sst_underscore_slug function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_underscore_slug [<arg>]…
The sst_underscore_slug function replaces every non-alphanumeric
character of the input with an underscore character.
The input is the space-separated concatenation of the arguments. If no arguments are given, the input is read from standard input in CSF form instead. The output is always written to standard output in CSF form.
sst_underscore_slug foo bar # foo_bar
sst_underscore_slug lib/libfoo.la # lib_libfoo_la
2.14.4. The sst_extract_archive function
sst_extract_archive <file>
The sst_extract_archive function extracts the archive <file> into
the current directory.
The supported file extensions are .tar, .tar.gz, .tar.xz, and
.zip.
2.14.5. The sst_get_distro function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_get_distro
The sst_get_distro function identifies the system type and stores it
in the sst_distro variable.
The following results are possible:
alpine,
arch,
centos,
cygwin,
debian,
fedora,
homebrew,
macports,
msys2,
rhel,
ubuntu,
or unknown.
The first time this function is called, it determines the result and
stores it in the sst_distro variable, and subsequent calls
simply output the cached result.
All possible results, including those added in the future, are
guaranteed to be spelled such that $sst_distro is unaffected by word
splitting and pathname expansion.
2.14.6. The sst_get_distro_version function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_get_distro_version
The sst_get_distro_version function identifies the system version and
stores it in the sst_distro_version variable.
The following results are possible for the various
sst_get_distro
values:
centos-
6,7,8, orunknown. ubuntu-
16.04,18.04,20.04, orunknown. unknown-
unknown.
The first time this function is called, it determines the result and
stores it in the sst_distro_version variable, and subsequent calls
simply output the cached result.
All possible results, including those added in the future, are
guaranteed to be spelled such that $sst_distro_version is unaffected
by word splitting and pathname expansion.
2.14.7. The prepare-dist-repo.bash script
prepare-dist-repo.bash <json>
The prepare-dist-repo.bash script makes a commit to a private
[bs_distribution_repository] for preview purposes before the
[bl_publish_dist_repo_bash] script is used to publish the
preview commit to a corresponding public distribution repository.
<json> specifies the JSON value on which to run jq.
If <json> is a single - character, the JSON value is
read from standard input.
Otherwise, if <json> begins with a /, A-Z, a-z,
0-9, ., _, or - character, it is taken to be a path to a file
from which to read the JSON value.
Otherwise, <json> is taken literally as the JSON value.
If the input is actually a sequence of JSON values, all but the first
JSON value is ignored.
The following arguments may be specified in <json>:
pull_repo-
The URL of the repository to clone and make the preview commit in. The commit will be made on top of the commit specified by
pull_commit.The URL will be expanded as if it appeared inside a double-quoted Bash string, allowing environment variables to be used. For example, a URL such as
https://gitlab-ci-token:${CI_JOB_TOKEN-}@gitlab.stealthsoftwareinc.com/stealth/sst.gitcould be used to clone a repository while running in a GitLab CI job.More than one URL may be specified by providing an array of strings instead of a single string. The array will act as a list of mirrors from which to try clone the repository. The mirrors are attempted to be cloned in order, stopping after the first successful clone that contains
pull_commit. pull_commit(optional)-
The commit of
pull_repoon top of which to make the preview commit. By default,pull_commitis the default branch ofpull_repo. push_repo-
A repository URL or an array of repository URLs to which to push the preview commit. The preview commit will always be pushed to a new branch
preview-<x>, where<x>is derived from the source of the CI job. This argument is optional and defaults topull_repo. update_script(optional)-
A path to an update script to run instead of the default update script.
post_update_script(optional)-
A path to a post-update script to run instead of the default post-update script. The default post-update script does nothing.
commit_script(optional)-
A path to a commit script to run instead of the default commit script.
post_commit_script(optional)-
A path to a post-commit script to run instead of the default post-commit script. The default post-commit script does nothing.
gitbundle-
The name of the
.gitbundlefile to produce as an artifact to use as input to the[bl_publish_dist_repo_bash]script. This argument is optional and defaults topreview.gitbundle. dist_archive-
A path to an archive to use instead of the default distribution archive, which is located using the
[bl_sst_find_dist_archive]function. This argument may also be set to “git-archive” to create an ephemeral distribution archive that contains the content ofHEADinside a container directory with an unspecified name. This argument is optional. tag_transform-
An optional
sedscript to use to transform the tag name when preparing from a tag.
2.14.8. The publish-dist-repo.bash script
publish-dist-repo.bash <json>
The publish-dist-repo.bash script publishes a preview commit made by
the [bl_prepare_dist_repo_bash] script to a corresponding public
[bs_distribution_repository].
2.14.9. The sst_find_dist_archive function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_find_dist_archive
2.14.10. The sst_find_dist_date function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_find_dist_date
2.14.11. The sst_find_dist_version function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_find_dist_version
2.14.12. The sst_type function
The sst_type function calls type "$@" and adjusts an exit
status of 1 to 0.
a.bash: You have awk. a.bash: You have sed. a.bash: You do not have nonexistent-program.
2.14.13. The sst_grep function
The sst_grep function calls grep "$@" and adjusts an exit
status of 1 to 0.
2.14.14. The sst_curl_slurp function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_curl_slurp <url> [<arg>]...
2.14.15. The sst_expect_utf8 function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_utf8 [<arg>]...
The sst_expect_utf8 function validates that the input is valid
UTF-8 and outputs the input unchanged.
2.14.16. The sst_get_variables function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_get_variables [<regex>...]
The sst_get_variables function outputs all existing variable
names that match any of the Bash regular expressions <regex>.
If more than one variable name matches, the names are separated by newline characters and the order of the names is unspecified. If no variable names match, the output is empty.
The output is written to standard output in CSF form.
2.14.17. The sst_get_environment_variables function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_get_environment_variables [<regex>...]
The sst_get_environment_variables function outputs all existing
environment variable names that match any of the
Bash regular expressions <regex>.
If more than one environment variable name matches, the names are separated by newline characters and the order of the names is unspecified. If no environment variable names match, the output is empty.
The output is written to standard output in CSF form.
$ cat a.bash #! /bin/sh - set -e || exit $? . sst.bash sst_get_environment_variables "$@" $ ./a.bash PWD OLDPWD PWD $ ./a.bash '^PWD' PWD $ ./a.bash ALL LC_ALL $ ./a.bash ALL PWD LC_ALL OLDPWD PWD $ PARALLEL=1 ./a.bash ALL LC_ALL PARALLEL $ ./a.bash && echo Note the blank line from CSF form. Note the blank line from CSF form.
2.14.18. The sst_human_list function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_human_list [<adjust>...] : [<item>...]
The sst_human_list function adjusts and outputs a list of items
in human-readable form.
-
If
<adjust>...is given, each<item>is adjusted by running and collecting the output of<adjust>... <item>. -
If no
<item>s are given, the output is “none”. -
If exactly one
<item>is given, the output is that<item>. -
If exactly two
<item>s are given, the output is those two<item>s with “and” inbetween. -
If three or more
<item>s are given, the output is all<item>s separated by “,”, and with “and” immediately preceding the last<item>.
The output is designed to appear after a : character in normal prose.
The output is written to standard output in CSF form.
$ cat a.bash #! /bin/sh - set -e || exit $? . sst.bash sst_human_list "$@" $ ./a.bash : none $ ./a.bash : foo foo $ ./a.bash : foo bar foo and bar $ ./a.bash : foo bar baz foo, bar, and baz $ ./a.bash : 'foo bar baz' foo bar baz $ ./a.bash sst_quote : none $ ./a.bash sst_quote : foo 'foo' $ ./a.bash sst_quote : foo bar 'foo' and 'bar' $ ./a.bash sst_quote : foo bar baz 'foo', 'bar', and 'baz' $ ./a.bash sst_quote : 'foo bar baz' 'foo bar baz'
2.14.19. The sst_kill_all_jobs function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_kill_all_jobs [<arg>...]
The sst_kill_all_jobs function runs
kill [<arg>...] %j
for every currently existing background job j.
If all of the kill commands succeed, the function will return
with exit status 0.
Otherwise, the function will return with the exit status of the
first failed kill command.
The rest of the kill commands will still be run, but their
exit statuses will be ignored.
Other errors are possible but extremely rare, and will cause the
function to immediately return with the offending exit status.
This differs from the usual fail-fast convention of the library, as the
main purpose of this function is for best-effort cleanup.
Because subshells do not inherit background jobs, the usual error
handling technique of using a subshell does not work, i.e.,
(sst_kill_all_jobs &>/dev/null) || :
will never find any background jobs to kill.
Note that the kill builtin may exit with exit status 0 in
certain cases you may not expect it to.
For example, on Bash 5.0,
(sleep 2 & kill foo %1 || echo bar)
will kill the sleep command and print an error message about
foo being unrecognized, but it will not print bar.
sst-example-17.bash#! /bin/sh -
set -e || exit $?
. sst.bash
# Kill all background jobs when this script exits.
sst_trap_append 'sst_kill_all_jobs &>/dev/null || :' EXIT
# Start a background job that runs for 30 seconds.
sleep 30 &
# After this script exits, you can run ps to verify that the sleep
# command isn't running. Then you can edit this script to remove the
# sst_kill_all_jobs command and try running it again. This time, you
# should see the sleep command in ps.
2.14.20. The sst_copyright_notice function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_copyright_notice <comment1> [<comment2> <comment3>] [<prose>]
The sst_copyright_notice function formats a copyright notice for
use in source code.
The prose of the copyright notice is specified by <prose> as follows:
-
If
<prose>is omitted, it will be taken to be the prose of the SST copyright notice, which is as follows:Copyright (C) Stealth Software Technologies, Inc. For the complete copyright information, please see the associated README file.
-
Otherwise, if
<prose>is-, it will be read from standard input in CSF form. -
Otherwise, if
<prose>begins with/or./, it will be read from the indicated file in CSF form. -
Otherwise,
<prose>will be taken directly in CSF form.
The comment structure of the copyright notice is specified by
<comment1>, <comment2>, and <comment3> as follows:
-
If
<comment2>and<comment3>are omitted, they are taken to be the same as<comment1>. -
Each line of
<prose>will be prefixed with<comment2>followed by a space character. -
<comment1>followed by a newline character will be prepended to the beginning of the copyright notice. -
A newline character followed by
<comment3>will be appended to the end of the copyright notice.
sst-example-18.bash#! /bin/sh -
set -e || exit $?
. sst.bash
sst_copyright_notice "$@"
$ ./sst-example-18.bash //
//
// Copyright (C) 2012-2024 Stealth Software Technologies, 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 (including
// the next paragraph) 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.
//
// SPDX-License-Identifier: MIT
//
$ ./sst-example-18.bash // Example
//
// Example
//
$ ./sst-example-18.bash '/*' ' *' ' */' Example
/*
* Example
*/
2.14.21. sst_is_errexit_suspended
The sst_is_errexit_suspended function outputs 1 if
errexit is suspended, 0 if errexit is not suspended, or
nothing if an error occurs.
The output is written to standard output in CSF form. However, if an error occurs, the output may be completely empty instead of a single newline character.
sst-example-19.bash#! /bin/sh -
set -e || exit $?
. sst.bash
sst_is_errexit_suspended # Outputs 0.
while sst_is_errexit_suspended; do break; done # Outputs 1.
until sst_is_errexit_suspended; do break; done # Outputs 1.
if sst_is_errexit_suspended; then :; fi # Outputs 1.
sst_is_errexit_suspended && : # Outputs 1.
sst_is_errexit_suspended || : # Outputs 1.
! sst_is_errexit_suspended # Outputs 1.
exit 0
2.15. Filesystem utilities
2.15.1. The sst_expect_any_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_any_file [<path>]...
The sst_expect_any_file function verifies that at least one <path>
exists as a file.
2.15.2. The sst_expect_extension function
sst_expect_extension <path> <extension>
The sst_expect_extension function verifies that the final component of
<path> ends with <extension>, but is not solely <extension>.
Technically speaking, this function verifies that <extension> is a
trailing substring of <path> that is preceded by at least one
non-slash character.
2.15.3. The sst_expect_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_file [<path>]...
The sst_expect_file function verifies that each <path> exists as a
file.
2.15.4. The sst_expect_maybe_file function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_maybe_file [<path>]...
The sst_expect_maybe_file function verifies that each <path> either
exists as a file or does not exist.
2.15.5. The sst_expect_not_exist function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_expect_not_exist [<path>...]
The sst_expect_not_exist function verifies that each <path>
does not exist.
If any verification fails, sst_barf will be called with an
appropriate error message.
2.15.6. sst_mkdir_p_new
sst_mkdir_p_new [<path>...]
The sst_mkdir_p_new function iterates through the <path>
parameters, taking the following actions for each <path>:
-
Create all parent directories of
<path>. If a parent directory already exists as a directory, it is skipped. If a parent directory already exists as a non-directory, a fatal error occurs. -
Create
<path>as a directory. If<path>already exists, a fatal error occurs.
If no <path> parameters are given, no action is taken.
2.15.7. sst_mkdir_p_only
sst_mkdir_p_only [<path>...]
The sst_mkdir_p_only function iterates through the <path>
parameters, taking the following actions for each <path>:
-
Create all parent directories of
<path>. If a parent directory already exists as a directory, it is skipped. If a parent directory already exists as a non-directory, a fatal error occurs.
If no <path> parameters are given, no action is taken.
This function behaves correctly under errexit suspension.
sst_mkdir_p_only # No action taken
sst_mkdir_p_only foo # Same as mkdir -p .
sst_mkdir_p_only foo/bar # Same as mkdir -p foo
2.15.8. The sst_popd function
The sst_popd function is equivalent to the popd builtin
except it does not write anything to standard output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.15.9. The sst_pushd function
The sst_pushd function is equivalent to the pushd builtin
except it does not write anything to standard output.
This function is unaffected by errexit suspension.
Errors will always cause the current shell to exit with a nonzero
exit status.
2.15.10. sst_stmpdir
#! /bin/sh -
set -e || exit $?
. sst.bash
readonly sst_stmpdir=d
The sst_stmpdir variable provides an absolute path to a directory
that can be used to store sensitive temporary files.
The path is guaranteed to begin with a “/” character and end with
a non-“/” character.
When the script exits, all files below the directory will be overwritten
with zeros and the directory will be deleted.
2.15.11. sst_tmpdir
#! /bin/sh -
set -e || exit $?
. sst.bash
readonly sst_tmpdir=d
The sst_tmpdir variable provides an absolute path to a directory
that can be used to store non-sensitive temporary files.
The path is guaranteed to begin with a “/” character and end with
a non-“/” character.
When the script exits, the directory will be deleted.
2.16. Autogen JSON handlers
The sst_ajh_build_tree_program_wrapper function
sst_ajh_build_tree_program_wrapper [ag_json...]
2.16.1. The sst_ajh_asciidoctor_document function
sst_ajh_asciidoctor_document [<json>...]
2.16.1.1. Images
asciidoctor will be called with -a imagesdir=images, meaning that
image::foo.png[] will reference images/foo.png, not foo.png.
So, to use images, create an images directory, put your images in it,
and reference them accordingly.
You can create subdirectories under the images directory to help
organize your images.
For example, if you create images/foo/bar.png, you can reference it
with image::foo/bar.png[].
Asciidoctor Diagram will output images to the images directory using
the name pattern
diag-*.
You should avoid this name pattern for your own images, as the build
system sometimes deletes all such images.
You can change the name of the images directory by setting imagesdir
in <json>.
2.16.2. The sst_ajh_java_library function
#! /bin/sh -
set -e || exit $?
. sst.bash
sst_ajh_java_library [<json>]…
jardeps-
An optional array of
.jarfiles thatdstdepends on. The following types of entries are supported:-
A
.jarfile name. For example, you might listnetty-all-4.1.65.Final.jar. The.jarfile will be expected to already exist injavadir,/usr/local/share/java, or/usr/share/javaat build time and after installation. If the.jarfile exists in more than one of these directories, the first one will be preferred. -
A makefile target for a
.jarfile. For example, you might listbuild-aux/downloads/netty-all-4.1.65.Final.jar. If an entry contains a/character, it is always assumed to be this type of entry. Otherwise, the entry is distinguished against a type 1 entry by the existence of a corresponding.ag,.ag.json,.ac, or.amfile. This type of entry behaves the same as a type 1 entry containing only the.jarfile name, except that additional code is generated for building and installing the.jarfile to the system (see below). -
An
.imsubstitution that expands to a.jarfile path (not merely a name). For example, you might list{@}PATH_NETTY{@}. This type of entry behaves the same as a type 1 entry except the path is determined at configure time instead of being semi-hardcoded to the previously described preference list. -
An
.imsubstitution that expands to a.jarfile path, followed by a:character, followed by a type 1 or type 2 entry. For example, you might list{@}PATH_NETTY{@}:build-aux/downloads/netty-all-4.1.65.Final.jar. This combines the effects of a type 3 entry with a type 1 or 2 entry, with the type 3 entry being preferred. You’d want to use this if you want to detect an already-installed newer version of a library at configure time, falling back to a known-good version if a newer version isn’t found. When followed by a type 2 entry, the generated installation code will only run if the.jarfile path does not exist as a file, i.e., the installation of the fallback will not occur if a newer version is already installed.
Several installation targets are generated to install any makefile target
.jarfiles from entry types 2 and 4:install-java-$(slug)-jardeps-targets-
Makes all makefile target
.jarfiles fordst. install-java-$(slug)-jardeps-
Installs all makefile target
.jarfiles fordst. install-java-jardeps-targets-
Makes all makefile target
.jarfiles everydst. install-java-jardeps-
Installs all makefile target
.jarfiles for everydst.
Do not use
jardepsto list.jardependencies that are built by this project. Usebuilt_jardepsinstead. -
built_jardeps-
An optional array of
.jarmakefile targets thatdstdepends on that are built by this project.
3. C/C++ library
3.1. Reserved identifiers
Unless explicitly stated otherwise in this manual, the following rules must be followed in any file that directly or indirectly includes any SST header file:
-
Do not define the identifier
SSTor any identifiers that begin withSST_anywhere, not even in local contexts. -
Do not define the identifier
sstor any identifiers that begin withsst_at file scope or as macros. -
Do not define any identifiers anywhere in the
::sstnamespace.
3.2. General development guidelines
This section provides guidelines for using the SST C/C++ library and writing C/C++ code in general.
3.3. Internal development guidelines
This section provides guidelines for working on the SST C/C++ library itself.
3.3.1. Header file extensions
The
public header files of the SST C/C++ library are those that live
below the src/c-cpp/include/sst directory in the SST Git repository,
but excluding those that live below the src/c-cpp/include/sst/private
directory.
All public SST header files use the .h file extension except for those
that are intended to be used in C++ only, which use the .hpp file
extension instead.
Sometimes you might find two copies of the same public SST header file
alongside each other: one with the .h file extension, and one with the
.hpp file extension.
In this case, including the .hpp header file in C++ is equivalent to
including the .h header file, but the .hpp header file is deprecated
and will eventually be removed.
If a header file is intended to be used in C++ only, it should include the following code after its include guard:
#ifndef __cplusplus
#error "This header file cannot be used in C"
#include "This header file cannot be used in C"
#endif
If a header file is intended to be used in C only, it should include the following code after its include guard:
#ifdef __cplusplus
#error "This header file cannot be used in C++"
#include "This header file cannot be used in C++"
#endif
3.4. Creating a self-contained subset library
SST includes a script that can create a self-contained subset library of the C/C++ library.
src/c-cpp/subset.bash [<option>]... [<entity>]...
subset.bash will produce an archive file sst.tar.gz that contains
all the necessary code for the given list of entities.
Each <entity> should be the name of a C/C++ entity, such as
sst_getbit or sst::bignum.
subset.bash must be run from the root of the SST project, i.e., the
same way as written in the above synopsis.
It will refuse to run if this is not the case.
For convenience, if the build system is not already
initialized
and
configured,
subset.bash will automatically run ./autogen and ./configure as
needed.
The output archive file will contain a directory named sst that
contains two subdirectories named include and lib.
sst/include contains all the necessary public header files, and
sst/lib contains all the necessary private implementation files.
The sst/include/sst/config.h file usually needs to be edited, as it
will be populated with values deduced from the current system, which may
not be correct for the ultimate destination of the subset library.
You’ll also need to remember to compile with -lfoo for the libraries
you choose to enable in config.h.
SST freely makes use of the standard threading utilities of C/C++, so
it’s reasonably likely you’ll also need to compile with -pthread (or
equivalent for your compiler).
If you fail to do so, the compilation can unfortunately sometimes still
succeed and result in strange errors at run time, such as calls to
std::call_once throwing exceptions.
--namespace=<namespace>-
Renames the
sstC++ namespace to<namespace>. TheSST_andsst_prefixes used for macros and C functions, the output archive file name, and all other names will also be renamed accordingly. It is permitted for<namespace>to have multiple components.As an example,
--namespace=foowill rename the C++ namespace tofoo, theSST_andsst_prefixes toFOO_andfoo_, and the output archive file tofoo.tar.gz. As another example,--namespace=foo::barwill rename the C++ namespace tofoo::bar, theSST_andsst_prefixes toFOO_BAR_andfoo_bar_, and the output archive file tofoo_bar.tar.gz.
The following commands will clone the SST distribution repository
and produce a self-contained subset library of the C/C++ library that
contains sst::bignum:
git clone https://github.com/stealthsoftwareinc/sst.git cd sst src/c-cpp/subset.bash sst::bignum
This will produce sst.tar.gz, which can be used in any other project.
Here’s how it could be used to compile a simple test program:
$ tar xzf sst.tar.gz $ cat <<'EOF' >a.cpp #include <iostream> #include <sst/catalog/bignum.hpp> int main() { std::cout << (sst::bignum(1) << 128).to_string() << "\n"; } EOF $ g++ -Isst/include -Isst/lib a.cpp $(find sst/lib -name '.c') -lcrypto $ ./a.out 340282366920938463463374607431768211456
3.5. Algorithm categories
3.5.1. Unique-pass algorithms
An algorithm with an iterator parameter p is called unique-pass
with respect to p if the algorithm satisfies all of the following
properties:
-
For any two arithmetic operations \(A\) and \(B\) performed on two iterators derived from
p(i.e., any of++q,q++,--q,q--,q+n,n+q,q+=n,q-n, orq-=nwhereqis derived fromp), either \(A\) is sequenced before \(B\) or \(B\) is sequenced before \(A\). In other words, all arithmetic operations on iterators derived frompare separated by sequence points. -
Each time an arithmetic operation \(A\) is performed on an iterator derived from
p, the next arithmetic operation is performed on the result of \(A\) or a copy of the result, even if \(A\) is trivial (e.g.,q+0). This induces a unique chain of iterators derived frompthat begins withpitself, where each successive iterator is the result of the next arithmetic operation on (a copy of) the previous iterator. -
For any two dereference operations \(A\) and \(B\) performed on (copies of) two iterators in the chain, either \(A\) is sequenced before \(B\) or \(B\) is sequenced before \(A\). In other words, all dereferences of (copies of) two iterators in the chain are separated by sequence points.
-
Each time an iterator derived from
pis dereferenced, the iterator is either the newest iterator or the second newest iterator in the chain. Furthermore, if it is the second newest iterator, then the newest iterator has not yet been dereferenced. This permits*p++and*p--but forbids sequences such asq=p++,*p,*q.
3.6. Attributes
3.6.1. The SST_MAYBE_UNUSED attribute
#include <sst/catalog/SST_MAYBE_UNUSED.h>
#define SST_MAYBE_UNUSED(...) /*...*/
3.6.2. The SST_NODISCARD attribute
#include <sst/catalog/SST_NODISCARD.h>
#define SST_NODISCARD(...) /*...*/
3.6.3. The SST_NORETURN attribute
#include <sst/catalog/SST_NORETURN.h>
#define SST_NORETURN(...) /*...*/
Depending on the language version being used, the SST_NORETURN
macro expands to either nothing or an attribute that specifies that a
function never returns.
Note that SST requires C++11, which supports the standard
[[noreturn]] attribute, so SST_NORETURN is not necessary
when using C++.
However, for consistency, it is provided anyway.
SST_NORETURN in Csst-example-22.c#include <stdlib.h>
#include <sst/catalog/SST_NORETURN.h>
SST_NORETURN() static void f() {
abort();
}
int main(void) {
f();
return 0; /* unreachable */
}
SST_NORETURN in C++sst-example-23.cpp#include <cstdlib>
#include <sst/catalog/SST_NORETURN.h>
namespace {
SST_NORETURN() void f() {
std::abort();
}
}
int main() {
f();
return 0; // unreachable
}
3.7. Debugging utilities
3.7.1. SST_ASSERT (C) (1)
#include <sst/catalog/SST_ASSERT.h>
#define SST_ASSERT(CONDITION) (x)
If SST_DEBUG is nonzero, the SST_ASSERT (C) (1) macro
expands to a parenthesized expression (x) of type void that
evaluates the expression CONDITION exactly once.
The following actions are then taken:
-
If the result of
CONDITIONcompares unequal to0, a message that indicates the assertion failed and includes the stringification ofCONDITIONis written to standard error, andabortis called. -
Otherwise, no action is taken.
Any message written to standard error will also include the
values of __FILE__ and __LINE__ from the location
of the SST_ASSERT (C) (1) call.
If SST_DEBUG is zero, the SST_ASSERT (C) (1) macro
expands to a parenthesized expression (x) of type void that takes no
action.
It does not evaluate CONDITION, except if the result of CONDITION is
a variable length array.
3.7.2. SST_ASSERT (C) (2)
#include <sst/catalog/SST_ASSERT.h>
#define SST_ASSERT(CONDITION, MESSAGE) (x)
If SST_DEBUG is nonzero, the SST_ASSERT (C) (2) macro
expands to a parenthesized expression (x) of type void that
evaluates the expression CONDITION exactly once.
The following actions are then taken:
-
If the result of
CONDITIONcompares unequal to0, the expressionMESSAGEis evaluated exactly once, a message that indicates the assertion failed and includesMESSAGEis written to standard error, andabortis called. The result ofMESSAGEmust be implicitly convertible tochar const *. If the result ofMESSAGEis a null pointer, it is adjusted to be the stringification ofCONDITIONinstead. -
Otherwise,
MESSAGEis not evaluated and no action is taken.
Any message written to standard error will also include the
values of __FILE__ and __LINE__ from the location
of the SST_ASSERT (C) (2) call.
If SST_DEBUG is zero, the SST_ASSERT (C) (2) macro
expands to a parenthesized expression (x) of type void that takes no
action.
It does not evaluate CONDITION, except if the result of CONDITION is
a variable length array, and it does not evaluate MESSAGE.
3.7.3. SST_ASSERT (C++) (1)
#include <sst/catalog/SST_ASSERT.hpp>
#define SST_ASSERT(CONDITION) (x)
If SST_DEBUG is nonzero, the SST_ASSERT (C++) (1)
macro expands to a parenthesized expression (x) of type void that
evaluates the expression CONDITION exactly once.
The following actions are then taken:
-
If
CONDITIONthrows an exceptione, a message that indicates the assertion was interrupted by an exception and includese.what()is written to standard error, andstd::abortis called. -
Otherwise, the result of
CONDITIONis explicitly converted tobool. If the result isfalse, a message that indicates the assertion failed and includes the stringification ofCONDITIONis written to standard error, andstd::abortis called. -
Otherwise, no action is taken.
Any message written to standard error will also include the
values of __FILE__ and __LINE__ from the
location of the SST_ASSERT (C++) (1) call.
If SST_DEBUG is zero, the SST_ASSERT (C++) (1)
macro expands to a parenthesized expression (x) of type void that
takes no action.
It does not evaluate CONDITION.
3.7.4. SST_ASSERT (C++) (2)
#include <sst/catalog/SST_ASSERT.hpp>
#define SST_ASSERT(CONDITION, MESSAGE) (x)
If SST_DEBUG is nonzero, the SST_ASSERT (C++) (2)
macro expands to a parenthesized expression (x) of type void that
evaluates the expression CONDITION exactly once.
The following actions are then taken:
-
If
CONDITIONthrows an exceptione, the expressionMESSAGEis not evaluated, a message that indicates the assertion was interrupted by an exception and includese.what()is written to standard error, andstd::abortis called. -
Otherwise, the result of
CONDITIONis explicitly converted tobool. If the result isfalse, the expressionMESSAGEis evaluated exactly once, a message that indicates the assertion failed and includesMESSAGEis written to standard error, andstd::abortis called. The result ofMESSAGEmust be implicitly convertible to eitherchar const *orstd::string const &. If the result ofMESSAGEis a null pointer, it is adjusted to be the stringification ofCONDITIONinstead. -
Otherwise,
MESSAGEis not evaluated and no action is taken.
Any message written to standard error will also include the
values of __FILE__ and __LINE__ from the
location of the SST_ASSERT (C++) (2) call.
If SST_DEBUG is zero, the SST_ASSERT (C++) (2)
macro expands to a parenthesized expression (x) of type void that
takes no action.
It does not evaluate CONDITION, and it does not evaluate MESSAGE.
3.7.5. SST_DEBUG
#include <sst/catalog/SST_DEBUG.h>
#define SST_DEBUG (x)
The SST_DEBUG macro expands to a parenthesized
integer constant expression (x) with type int.
The expression is also suitable for use in the preprocessor.
3.8. Memory utilities
3.8.1. The sst::overlap function
#include <sst/catalog/overlap.hpp>
namespace sst {
template<class T1, std::integral N1, class T2, std::integral N2>
bool overlap(T1 const * p1, N1 n1, T2 const * p2, N2 n2);
template<class T1, std::integral N1, class T2>
bool overlap(T1 const * p1, N1 n1, T2 const * p2);
template<class T1, class T2, std::integral N2>
bool overlap(T1 const * p1, T2 const * p2, N2 n2);
template<class T1, class T2>
bool overlap(T1 const * p1, T2 const * p2);
}
The sst::overlap function attempts to determine whether two memory
regions overlap.
Each memory region consists of the n\(i\) elements of type
T\(i\) beginning at p\(i\).
n\(i\) must be nonnegative and p\(i\) must be a valid
pointer, even if n\(i\) is zero.
If n\(i\) is omitted, it is taken to be 1.
T\(i\) must be an object type or void.
If T\(i\) is void, the behavior is as if it were
unsigned char.
If this function returns true, the two memory regions overlap.
If this function returns false, the two memory regions may or may not
overlap.
False negatives are generally possible because some systems allow
multiple memory regions to refer to the same underlying data.
For example, a system may allow the same file to be mapped into two
different memory regions at the same time, with any changes being
reflected in both regions simultaneously.
If no such functionality is being used, false negatives are not
possible.
If n1 or n2 is zero, this function always returns false.
3.8.2. The sst::pointer_eq function
#include <sst/catalog/pointer_eq.hpp>
namespace sst {
template<class T1, class T2>
bool pointer_eq(T1 const * p1, T2 const * p2);
}
The sst::pointer_eq function returns true if p1 is
equal to p2 with respect to the
implementation-defined strict total order over pointers.
Each of T1 and T2 must be either void or an object type.
3.8.3. The sst::pointer_ge function
#include <sst/catalog/pointer_ge.hpp>
namespace sst {
template<class T1, class T2>
bool pointer_ge(T1 const * p1, T2 const * p2);
}
The sst::pointer_ge function returns true if p1 is
greater than or equal to p2 with respect to the
implementation-defined strict total order over pointers.
Each of T1 and T2 must be either void or an object type.
3.8.4. The sst::pointer_gt function
#include <sst/catalog/pointer_gt.hpp>
namespace sst {
template<class T1, class T2>
bool pointer_gt(T1 const * p1, T2 const * p2);
}
The sst::pointer_gt function returns true if p1 is
greater than p2 with respect to the
implementation-defined strict total order over pointers.
Each of T1 and T2 must be either void or an object type.
3.8.5. The sst::pointer_le function
#include <sst/catalog/pointer_le.hpp>
namespace sst {
template<class T1, class T2>
bool pointer_le(T1 const * p1, T2 const * p2);
}
The sst::pointer_le function returns true if p1 is
less than or equal to p2 with respect to the
implementation-defined strict total order over pointers.
Each of T1 and T2 must be either void or an object type.
3.8.6. The sst::pointer_lt function
#include <sst/catalog/pointer_lt.hpp>
namespace sst {
template<class T1, class T2>
bool pointer_lt(T1 const * p1, T2 const * p2);
}
The sst::pointer_lt function returns true if p1 is
less than p2 with respect to the
implementation-defined strict total order over pointers.
Each of T1 and T2 must be either void or an object type.
3.8.7. The sst::pointer_ne function
#include <sst/catalog/pointer_ne.hpp>
namespace sst {
template<class T1, class T2>
bool pointer_ne(T1 const * p1, T2 const * p2);
}
The sst::pointer_ne function returns true if p1 is
not equal to p2 with respect to the
implementation-defined strict total order over pointers.
Each of T1 and T2 must be either void or an object type.
3.9. Language shims
3.9.1. The SST_C_VALUE macros
#include <sst/SST_C_VALUE.h>
// or: <sst/language.h>
#define SST_C99_VALUE 199901L
#define SST_C11_VALUE 201112L
#define SST_C17_VALUE 201710L
#define SST_C18_VALUE SST_C17_VALUE
3.9.2. The SST_C_OR_LATER macros
#include <sst/SST_C_OR_LATER.h>
// or: <sst/language.h>
#define SST_C99_OR_LATER (__STDC_VERSION__ >= SST_C99_VALUE)
#define SST_C11_OR_LATER (__STDC_VERSION__ >= SST_C11_VALUE)
#define SST_C17_OR_LATER (__STDC_VERSION__ >= SST_C17_VALUE)
#define SST_C18_OR_LATER (__STDC_VERSION__ >= SST_C18_VALUE)
3.9.3. The SST_CPP_VALUE macros
#include <sst/SST_CPP_VALUE.h>
// or: <sst/language.h>
#define SST_CPP97_VALUE 199711L
#define SST_CPP03_VALUE SST_CPP97_VALUE
#define SST_CPP11_VALUE 201103L
#define SST_CPP14_VALUE 201402L
#define SST_CPP17_VALUE 201703L
#define SST_CPP20_VALUE 202002L
3.9.4. The SST_CPP_OR_LATER macros
#include <sst/SST_CPP_OR_LATER.h>
// or: <sst/language.h>
#define SST_CPP97_OR_LATER (__cplusplus >= SST_CPP97_VALUE)
#define SST_CPP03_OR_LATER (__cplusplus >= SST_CPP03_VALUE)
#define SST_CPP11_OR_LATER (__cplusplus >= SST_CPP11_VALUE)
#define SST_CPP14_OR_LATER (__cplusplus >= SST_CPP14_VALUE)
#define SST_CPP17_OR_LATER (__cplusplus >= SST_CPP17_VALUE)
#define SST_CPP20_OR_LATER (__cplusplus >= SST_CPP20_VALUE)
3.9.5. The SST_STATIC_ASSERT macro
#include <sst/language.h>
#define SST_STATIC_ASSERT(constant_expression) ...
3.9.6. The SST_CPP_CONSTEXPR macros
#include <sst/SST_CPP_CONSTEXPR.hpp>
// or: <sst/language.h>
#if SST_CPP14_OR_LATER
#define SST_CPP14_CONSTEXPR constexpr
#else
#define SST_CPP14_CONSTEXPR
#endif
#if SST_CPP17_OR_LATER
#define SST_CPP17_CONSTEXPR constexpr
#else
#define SST_CPP17_CONSTEXPR
#endif
#if SST_CPP20_OR_LATER
#define SST_CPP20_CONSTEXPR constexpr
#else
#define SST_CPP20_CONSTEXPR
#endif
The SST_CPP14_CONSTEXPR macro expands to the constexpr keyword
if C++14 or later is being used, or to nothing if not.
The SST_CPP17_CONSTEXPR macro expands to the constexpr keyword
if C++17 or later is being used, or to nothing if not.
The SST_CPP20_CONSTEXPR macro expands to the constexpr keyword
if C++20 or later is being used, or to nothing if not.
3.9.7. The SST_CPP_INLINE macros
#include <sst/catalog/SST_CPP17_INLINE.hpp>
// or: <sst/language.h>
#if SST_CPP17_OR_LATER
#define SST_CPP17_INLINE inline
#else
#define SST_CPP17_INLINE
#endif
The SST_CPP17_INLINE macro expands to the inline keyword if
C++17 or later is being used, or to nothing if not.
3.9.8. The SST_CONSTEXPR_ASSERT macro
#include <sst/catalog/SST_CONSTEXPR_ASSERT.hpp>
// or: <sst/language.h>
#if SST_CPP14_OR_LATER
#define SST_CONSTEXPR_ASSERT(x) assert(x)
#else
#define SST_CONSTEXPR_ASSERT(x)
#endif
The SST_CONSTEXPR_ASSERT macro can be used to run dynamic assertions
in constexpr functions.
3.9.9. The SST_EXTERN_C macro
#include <sst/catalog/SST_EXTERN_C.h>
#ifdef __cplusplus
#define SST_EXTERN_C extern "C"
#else
#define SST_EXTERN_C extern
#endif
3.10. Type traits
3.10.1. The sst::bool_constant alias
#include <sst/catalog/bool_constant.hpp>
namespace sst {
template<bool B>
using bool_constant = std::integral_constant<bool, B>;
}
The sst::bool_constant alias provides a convenient way to write
std::integral_constant<bool, B>.
The
sst::bool_constant
alias
was added to the library because the
std::bool_constant
alias
is not available below
C++17.
3.10.2. sst::common_type_t
#include <sst/catalog/common_type_t.hpp>
namespace sst {
template<class... T>
using common_type_t =
typename std::common_type<T...>::type;
}
The
sst::common_type_t
alias provides a convenient way to write
std::common_type<T...>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
The
sst::common_type_t
alias
was added to the library because the
std::common_type_t
alias
is not available below
C++14.
sst-example-24.cpp#include <type_traits>
#include <sst/catalog/common_type_t.hpp>
template<class... T>
class foo {
// OK.
using type1 = typename std::common_type<T...>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = std::common_type<T...>::type;
// OK.
using type3 = sst::common_type_t<T...>;
};
int main() {
return 0;
}
g++ sst-example-24.cpp -lsst
3.10.3. sst::conditional_t
#include <sst/catalog/conditional_t.hpp>
namespace sst {
template<bool B, class T, class F>
using conditional_t =
typename std::conditional<B, T, F>::type;
}
The
sst::conditional_t
alias provides a convenient way to write
std::conditional<B, T, F>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
The
sst::conditional_t
alias
was added to the library because the
std::conditional_t
alias
is not available below
C++14.
sst-example-25.cpp#include <type_traits>
#include <sst/catalog/conditional_t.hpp>
template<bool B, class T, class F>
class foo {
// OK.
using type1 = typename std::conditional<B, T, F>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = std::conditional<B, T, F>::type;
// OK.
using type3 = sst::conditional_t<B, T, F>;
};
int main() {
return 0;
}
g++ sst-example-25.cpp -lsst
3.10.4. The sst::copy_cv trait
#include <sst/catalog/copy_cv.hpp>
namespace sst {
template<class Src, class Dst>
struct copy_cv
: sst::type_identity<R> {};
}
The sst::copy_cv trait defines R to be Dst overwritten with
the cv-qualifiers of Src.
In other words, the following steps take place:
-
Begin with
R = Dst. -
Update
Rby removing any cv-qualifiers. -
Update
Rby adding any cv-qualifiers fromSrc.
3.10.5. sst::copy_cv_t
#include <sst/catalog/copy_cv_t.hpp>
namespace sst {
template<class Src, class Dst>
using copy_cv_t =
typename sst::copy_cv<Src, Dst>::type;
}
The
sst::copy_cv_t
alias provides a convenient way to write
sst::copy_cv<Src, Dst>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
sst-example-26.cpp#include <sst/catalog/copy_cv.hpp>
#include <sst/catalog/copy_cv_t.hpp>
template<class Src, class Dst>
class foo {
// OK.
using type1 = typename sst::copy_cv<Src, Dst>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = sst::copy_cv<Src, Dst>::type;
// OK.
using type3 = sst::copy_cv_t<Src, Dst>;
};
int main() {
return 0;
}
g++ sst-example-26.cpp -lsst
3.10.6. sst::decay_t
#include <sst/catalog/decay_t.hpp>
namespace sst {
template<class T>
using decay_t =
typename std::decay<T>::type;
}
The
sst::decay_t
alias provides a convenient way to write
std::decay<T>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
The
sst::decay_t
alias
was added to the library because the
std::decay_t
alias
is not available below
C++14.
sst-example-27.cpp#include <type_traits>
#include <sst/catalog/decay_t.hpp>
template<class T>
class foo {
// OK.
using type1 = typename std::decay<T>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = std::decay<T>::type;
// OK.
using type3 = sst::decay_t<T>;
};
int main() {
return 0;
}
g++ sst-example-27.cpp -lsst
3.10.7. The sst::is_arithmetic trait
#include <sst/catalog/is_arithmetic.hpp>
namespace sst {
template<class T>
struct is_arithmetic
: sst::bool_constant<B> {};
}
3.10.8. The sst::is_arithmetic_ish trait
#include <sst/catalog/is_arithmetic_ish.hpp>
namespace sst {
template<class T>
struct is_arithmetic_ish
: sst::bool_constant<B> {};
}
3.10.9. The sst::is_arithmetic_like trait
#include <sst/catalog/is_arithmetic_like.hpp>
namespace sst {
template<class T>
struct is_arithmetic_like
: sst::bool_constant<B> {};
}
3.10.10. The sst::is_big_endian trait
#include <sst/catalog/is_big_endian.hpp>
namespace sst {
template<class T>
struct is_big_endian : std::integral_constant<bool, b>;
}
The sst::is_big_endian trait determines whether the byte ordering
of T is big endian.
Any cv-qualifiers on T are ignored.
The sst::is_big_endian trait may produce false negatives.
|
Important
|
Since |
3.10.11. The sst::is_bool type trait
#include <sst/catalog/is_bool.hpp>
namespace sst {
template<class T>
struct sst::is_bool
: std::integral_constant<bool, see below> {};
}
The sst::is_bool type trait determines whether T is the type
bool, ignoring any references and cv-qualifiers.
|
Important
|
It is recommended to always extract the value of |
3.10.12. sst::is_byte
#include <sst/catalog/is_byte.hpp>
namespace sst {
template<class T>
struct is_byte
: std::integral_constant<bool, v> {};
}
The sst::is_byte trait determines whether T is one of the
following types, ignoring any reference and cv-qualifiers:
-
char -
signed char -
unsigned char
3.10.13. sst::is_byte_input_iterable
#include <sst/catalog/is_byte_input_iterable.hpp>
namespace sst {
template<class C>
struct is_byte_input_iterable
: std::integral_constant<bool, v> {};
}
3.10.14. sst::is_byte_input_iterator
#include <sst/catalog/is_byte_input_iterator.hpp>
namespace sst {
template<class I>
struct is_byte_input_iterator
: std::integral_constant<bool, v> {};
}
3.10.15. The sst::is_enum type trait
#include <sst/catalog/is_enum.hpp>
namespace sst {
template<class T>
struct sst::is_enum
: std::integral_constant<bool, see below> {};
}
The sst::is_enum type trait determines whether T is an
enumeration type, ignoring any references and cv-qualifiers.
|
Important
|
It is recommended to always extract the value of |
3.10.16. The sst::is_exact_width_integer trait
#include <sst/catalog/is_exact_width_integer.hpp>
namespace sst {
template<class T>
struct is_exact_width_integer : std::integral_constant<bool, b>;
}
The sst::is_exact_width_integer trait determines whether T is one of
the exact-width integer types, i.e., one of
int8_t,
uint8_t,
int16_t,
uint16_t,
int32_t,
uint32_t,
int64_t,
or
uint64_t,
ignoring any cv-qualifiers.
|
Important
|
Since |
3.10.17. The sst::is_floating trait
#include <sst/catalog/is_floating.hpp>
namespace sst {
template<class T>
struct is_floating
: sst::bool_constant<B> {};
}
3.10.18. The sst::is_floating_ish trait
#include <sst/catalog/is_floating_ish.hpp>
namespace sst {
template<class T>
struct is_floating_ish
: sst::bool_constant<B> {};
}
3.10.19. The sst::is_floating_like trait
#include <sst/catalog/is_floating_like.hpp>
namespace sst {
template<class T>
struct is_floating_like
: sst::bool_constant<B> {};
}
3.10.20. The sst::is_input_iterator trait
#include <sst/catalog/is_input_iterator.hpp>
namespace sst {
template<class I,
template<class...> class heheT = sst::dependent_true,
class... Args>
struct is_input_iterator
: sst::bool_constant<b> {};
}
Let i be an object of type sst::decay_t<I>.
The sst::is_input_iterator trait defines b to true if all of
the following are true:
-
sst::is_iterator<I>::valueistrue. -
*iis an lvalue reference to an object type. -
T<sst::decay_t<decltype(*i)>, Args...>::valueistrue.
3.10.21. The sst::is_integer trait
#include <sst/catalog/is_integer.hpp>
namespace sst {
template<class T>
struct is_integer
: sst::bool_constant<B> {};
}
The sst::is_integer trait defines B to true if T is a
fundamental integer type[3], ignoring any cvref-qualifiers.
3.10.22. The sst::is_integer_ish trait
#include <sst/catalog/is_integer_ish.hpp>
namespace sst {
template<class T>
struct is_integer_ish
: sst::bool_constant<B> {};
}
3.10.23. The sst::is_integer_like trait
#include <sst/catalog/is_integer_like.hpp>
namespace sst {
template<class T>
struct is_integer_like
: sst::bool_constant<B> {};
}
3.10.24. The sst::is_iterator trait
#include <sst/catalog/is_iterator.hpp>
namespace sst {
template<class I>
struct is_iterator
: sst::bool_constant<b> {};
}
Let i be an object of type sst::decay_t<I>.
The sst::is_iterator trait defines b to true if all of the
following are true:
-
*icompiles. -
++ihas typesst::decay_t<I> &.
3.10.25. The sst::is_little_endian trait
#include <sst/catalog/is_little_endian.hpp>
namespace sst {
template<class T>
struct is_little_endian : std::integral_constant<bool, b>;
}
The sst::is_little_endian trait determines whether the byte ordering
of T is little endian.
Any cv-qualifiers on T are ignored.
The sst::is_little_endian trait may produce false negatives.
|
Important
|
Since |
3.10.26. The sst::is_non_bool_integer trait
#include <sst/type.h>
namespace sst {
template<class T>
struct is_non_bool_integer {
constexpr bool value = /* ... */;
};
}
The sst::is_non_bool_integer class defines value to be true if T
is a possibly cv-qualified integer type other than bool, or false if
not.
3.10.27. The sst::is_ones_complement trait
#include <sst/type.h>
namespace sst {
template<class T>
struct is_ones_complement : std::integral_constant<bool, b>;
}
The sst::is_ones_complement class determines whether T is an
integer type that uses ones’ complement representation.
In C++20 and later, signed integer types are required to use two’s complement representation[4]. Before C++20, signed integer types are permitted to use ones’ complement or sign-magnitude representation instead, in which case negative zero may be a trap representation[5].
Unsigned integer types are never considered to use ones’ complement representation.
|
Important
|
Since |
3.10.28. The sst::is_output_iterator trait
#include <sst/catalog/is_output_iterator.hpp>
namespace sst {
template<class I, class T>
struct is_output_iterator
: sst::bool_constant<b> {};
}
Let i be an object of type sst::decay_t<I>.
The sst::is_output_iterator trait defines b to true if all
of the following are true:
-
sst::is_iterator<I>::valueistrue. -
*i = std::forward<T>(std::declval<T>())compiles.
3.10.29. sst::is_sentinel
#include <sst/catalog/is_sentinel.hpp>
namespace sst {
template<class S, class I>
struct is_sentinel
: std::integral_constant<bool, v> {};
}
3.10.30. sst::is_value_sentinel
#include <sst/catalog/is_value_sentinel.hpp>
namespace sst {
template<class S, class I>
struct is_value_sentinel
: std::integral_constant<bool, v> {};
}
3.10.31. The sst::is_sign_magnitude trait
#include <sst/type.h>
namespace sst {
template<class T>
struct is_sign_magnitude : std::integral_constant<bool, b>;
}
The sst::is_sign_magnitude class determines whether T is an
integer type that uses sign-magnitude representation.
In C++20 and later, signed integer types are required to use two’s complement representation[4]. Before C++20, signed integer types are permitted to use ones’ complement or sign-magnitude representation instead, in which case negative zero may be a trap representation[5].
Unsigned integer types are never considered to use sign-magnitude representation.
|
Important
|
Since |
3.10.32. The sst::is_signed_integer trait
#include <sst/catalog/is_signed_integer.hpp>
// or: <sst/type.h>
namespace sst {
template<class T>
struct is_signed_integer : std::integral_constant<bool, b>;
}
The sst::is_signed_integer trait determines whether T is a signed
fundamental integer type[3].
|
Important
|
Since |
3.10.33. The sst::is_twos_complement trait
#include <sst/type.h>
namespace sst {
template<class T>
struct is_twos_complement : std::integral_constant<bool, b>;
}
The sst::is_twos_complement class determines whether T is an
integer type that uses two’s complement representation.
In C++20 and later, signed integer types are required to use two’s complement representation[4]. Before C++20, signed integer types are permitted to use ones’ complement or sign-magnitude representation instead, in which case negative zero may be a trap representation[5].
Unsigned integer types are always considered to use two’s complement representation.
|
Important
|
Since |
3.10.34. The sst::is_unsigned_integer trait
#include <sst/type.h>
namespace sst {
template<class T>
struct is_unsigned_integer {
constexpr bool value = /* ... */;
};
}
The sst::is_unsigned_integer class defines value to be true if T
is a possibly cv-qualified unsigned integer type, or false if not.
For more information, see std::is_unsigned and
std::is_integral.
3.10.35. sst::remove_cv_t
#include <sst/catalog/remove_cv_t.hpp>
namespace sst {
template<class T>
using remove_cv_t =
typename std::remove_cv<T>::type;
}
The
sst::remove_cv_t
alias provides a convenient way to write
std::remove_cv<T>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
The
sst::remove_cv_t
alias
was added to the library because the
std::remove_cv_t
alias
is not available below
C++14.
sst-example-28.cpp#include <type_traits>
#include <sst/catalog/remove_cv_t.hpp>
template<class T>
class foo {
// OK.
using type1 = typename std::remove_cv<T>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = std::remove_cv<T>::type;
// OK.
using type3 = sst::remove_cv_t<T>;
};
int main() {
return 0;
}
g++ sst-example-28.cpp -lsst
3.10.36. The sst::remove_cvref trait
#include <sst/catalog/remove_cvref.hpp>
namespace sst {
template<class T>
struct remove_cvref
: sst::type_identity<R> {};
}
The sst::remove_cvref trait defines R to be T with any
reference and cv-qualifiers removed.
In other words, the following steps take place:
-
Begin with
R = T. -
If
Ris a reference type, updateRto be the referenced type. -
Update
Rby removing any topmost cv-qualifiers.
The
sst::remove_cvref
trait
was added to the library because the
std::remove_cvref
trait
is not available below
C++20.
sst::remove_cvref<int>::type // int
sst::remove_cvref<int &>::type // int
sst::remove_cvref<int const>::type // int
sst::remove_cvref<int const &>::type // int const
3.10.37. sst::remove_cvref_t
#include <sst/catalog/remove_cvref_t.hpp>
namespace sst {
template<class T>
using remove_cvref_t =
typename std::remove_cvref<T>::type;
}
The
sst::remove_cvref_t
alias provides a convenient way to write
std::remove_cvref<T>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
sst-example-30.cpp#include <sst/catalog/remove_cvref.hpp>
#include <sst/catalog/remove_cvref_t.hpp>
template<class T>
class foo {
// OK.
using type1 = typename std::remove_cvref<T>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = std::remove_cvref<T>::type;
// OK.
using type3 = sst::remove_cvref_t<T>;
};
int main() {
return 0;
}
g++ sst-example-30.cpp -lsst
3.10.38. sst::remove_reference_t
#include <sst/catalog/remove_reference_t.hpp>
namespace sst {
template<class T>
using remove_reference_t =
typename std::remove_reference<T>::type;
}
The
sst::remove_reference_t
alias provides a convenient way to write
std::remove_reference<T>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
The
sst::remove_reference_t
alias
was added to the library because the
std::remove_reference_t
alias
is not available below
C++14.
sst-example-31.cpp#include <type_traits>
#include <sst/catalog/remove_reference_t.hpp>
template<class T>
class foo {
// OK.
using type1 = typename std::remove_reference<T>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = std::remove_reference<T>::type;
// OK.
using type3 = sst::remove_reference_t<T>;
};
int main() {
return 0;
}
g++ sst-example-31.cpp -lsst
3.10.39. The sst::type_identity trait
#include <sst/catalog/type_identity.hpp>
namespace sst {
template<class T>
struct type_identity {
using type = T;
};
}
The sst::type_identity trait defines type to be T itself.
The
sst::type_identity
trait
was added to the library because the
std::type_identity
trait
is not available below
C++20.
3.10.40. sst::type_identity_t
#include <sst/catalog/type_identity_t.hpp>
namespace sst {
template<class T>
using type_identity_t =
typename sst::type_identity<T>::type;
}
The
sst::type_identity_t
alias provides a convenient way to write
sst::type_identity<T>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
sst-example-32.cpp#include <sst/catalog/type_identity.hpp>
#include <sst/catalog/type_identity_t.hpp>
template<class T>
class foo {
// OK.
using type1 = typename sst::type_identity<T>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = sst::type_identity<T>::type;
// OK.
using type3 = sst::type_identity_t<T>;
};
int main() {
return 0;
}
g++ sst-example-32.cpp -lsst
3.10.41. The sst::undeduced trait
#include <sst/catalog/undeduced.hpp>
namespace sst {
template<class T>
struct undeduced
: sst::type_identity<R> {};
}
The sst::undeduced trait defines R to T itself, making it
functionally equivalent to the sst::type_identity trait.
The difference is only of style: both of these traits can be used to
prevent template argument deduction from occurring, in which case
using sst::undeduced is a better indication of intent than using
sst::type_identity.
sst-example-33.cpp#include <sst/catalog/undeduced_t.hpp>
template<class T>
void f(T, T) {}
template<class T>
void g(T, sst::undeduced_t<T>) {}
int main() {
long x = 0;
int y = 0;
// Compilation error: it is ambiguous whether T should be deduced from
// x as long or from y as int.
f(x, y);
// OK: T is deduced from x as long.
g(x, y);
}
3.10.42. sst::undeduced_t
#include <sst/catalog/undeduced_t.hpp>
namespace sst {
template<class T>
using undeduced_t =
typename sst::undeduced<T>::type;
}
The
sst::undeduced_t
alias provides a convenient way to write
sst::undeduced<T>::type
that never requires the
typename
keyword to be used to disambiguate a dependent type.
sst-example-34.cpp#include <sst/catalog/undeduced.hpp>
#include <sst/catalog/undeduced_t.hpp>
template<class T>
class foo {
// OK.
using type1 = typename sst::undeduced<T>::type;
// Compilation error in C++11: the typename keyword is required.
using type2 = sst::undeduced<T>::type;
// OK.
using type3 = sst::undeduced_t<T>;
};
int main() {
return 0;
}
g++ sst-example-34.cpp -lsst
3.11. Iterator utilities
3.11.3. The sst::count_it function
#include <sst/catalog/count_it.hpp>
namespace sst {
template<Iterator T, std::integral N>
R count_it(T x, N n);
}
The sst::count_it function returns an iterator that compares equal
to the iterator that would be produced by std::advance(x, n).
The type R of the returned iterator is unspecified.
However, the following guarantees are made:
-
The return types of
sst::count_it(x, n)andsst::wrap_it(x, n)are the same. -
The return types of
sst::count_it(x, n)andsst::wrap_it(x, n)are the same.
3.11.4. The sst::track_it function
The sst::track_it function returns an iterator that wraps another
iterator with functionality for tracking and limiting the iterator’s
motion.
3.11.4.1. The sst::track_it function (overload 1)
#include <sst/catalog/track_it.hpp>
namespace sst {
template<
class Count = int,
class Iterator,
sst::enable_if_t<
sst::is_integer<Count>::value
> = 0>
W track_it(Iterator & i);
}
The sst::track_it function (overload 1) returns an iterator that behaves like
i, except it stores a pointer to i and updates i as it moves.
The returned iterator may only be used in a unique-pass algorithm.
The type W of the returned iterator is unspecified.
However, the following guarantees are made:
-
Provided they are called with the same
CountandIteratortypes, the return types ofsst::track_it(overload 1) and anysst::count_itoverload are the same. -
Provided they are called with the same
CountandIteratortypes, the return types ofsst::track_it(overload 1) and anysst::wrap_itoverload are the same.
3.11.4.2. The sst::track_it function (overload 2)
#include <sst/catalog/track_it.hpp>
namespace sst {
template<
class Count,
class Iterator,
sst::enable_if_t<
sst::is_integer<Count>::value
> = 0>
W track_it(Iterator & i, Count n);
}
3.11.4.3. The sst::track_it function (overload 3)
#include <sst/catalog/track_it.hpp>
namespace sst {
template<
class Count,
class Iterator,
sst::enable_if_t<
sst::is_integer<Count>::value
> = 0>
W track_it(Iterator & i, Count * n);
}
3.11.5. The sst::wrap_it function
The sst::wrap_it function returns an iterator that wraps another
iterator with functionality for tracking and limiting the iterator’s
motion.
3.11.5.1. The sst::wrap_it function (overload 1)
#include <sst/catalog/wrap_it.hpp>
namespace sst {
template<
class Count = int,
class Iterator,
sst::enable_if_t<
sst::is_integer<Count>::value
> = 0>
W wrap_it(Iterator i);
}
The sst::wrap_it function (overload 1) returns an iterator that behaves like
i.
The returned iterator may only be used in a unique-pass algorithm.
The type W of the returned iterator is unspecified.
However, the return types of all sst::count_it,
sst::track_it, and sst::wrap_it overloads are the same
provided they are called with the same Count and Iterator types.
The main purpose of this overload is to achieve type equality in cases
where i is associated with another sst::count_it,
sst::track_it, or sst::wrap_it iterator and the iterators
are being passed to an algorithm that requires them to have the same
type.
For example, std::copy requires its first two arguments to have
the same type, so passing i and sst::count_it(i, 10) will fail
to compile, but passing sst::wrap_it(i) and
sst::count_it(i, 10) will work.
In this case, you must also be careful to ensure that both iterators
have the same Count type.
Continuing the example, if we were copying n elements instead of 10,
we could pass sst::wrap_it<decltype(n)>(i) and
sst::count_it(i, n).
3.11.5.2. The sst::wrap_it function (overload 2)
#include <sst/catalog/wrap_it.hpp>
namespace sst {
template<
class Count,
class Iterator,
sst::enable_if_t<
sst::is_integer<Count>::value
> = 0>
W wrap_it(Iterator i, Count n);
}
3.11.5.3. The sst::wrap_it function (overload 3)
#include <sst/catalog/wrap_it.hpp>
namespace sst {
template<
class Count,
class Iterator,
sst::enable_if_t<
sst::is_integer<Count>::value
> = 0>
W wrap_it(Iterator i, Count * n);
}
3.12. JSON utilities
The following functions are provided for convenience.
They are equivalent to the corresponding sst::json::get_to functions
except they return their results by value instead of having dst
parameters:
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/json/get_as.hpp[sst/catalog/json/get_as.hpp,window=_blank]>
namespace sst::json {
template<class ValueType, class Json>
ValueType get_as(Json const & src) { ... }
template<class ValueType, class Json>
ValueType get_as(Json const & src,
typename Json::object_t::key_type const & key) { ... }
template<class ValueType, class Json>
ValueType get_as(Json const & src,
typename Json::object_t::key_type const & key,
ValueType const & default_value) { ... }
}
3.12.1. The sst::json::exception class
#include <sst/catalog/json/exception.hpp>
namespace sst::json {
class exception : public std::runtime_error {
};
}
3.12.2. The sst::json::get_from_file function
#include <sst/catalog/json/get_from_file.hpp>
namespace sst::json {
template<class T, class NlohmannJson = T, class CharT = char>
T get_from_file(std::string const & src);
template<class T, class NlohmannJson = T, class CharT = char>
T get_from_file(char const * const src);
}
3.12.3. The sst::json::get_as_file function
#include <sst/catalog/json/get_as_file.hpp>
namespace sst::json {
template<class CharT = char, class NlohmannJson>
void get_as_file(NlohmannJson const & src,
std::string const & dst,
int indent = 2);
template<class CharT = char, class NlohmannJson>
void get_as_file(NlohmannJson const & src,
char const * const dst,
int indent = 2);
}
3.12.4. The sst::json::get_to function
#include <sst/catalog/json/get_to.hpp>
namespace sst::json {
//
// Integer destinations
//
// (1)
template<class ValueType,
class NlohmannJson,
typename sst::enable_if<
std::is_integral<ValueType>::value>::type = 0>
ValueType & get_to(NlohmannJson const & src, ValueType & dst);
// (2)
template<class ValueType,
class NlohmannJson,
typename sst::enable_if<
std::is_same<ValueType, BIGNUM>::value>::type = 0>
ValueType & get_to(NlohmannJson const & src, ValueType & dst);
// (3)
template<class ValueType,
class NlohmannJson,
typename sst::enable_if<
std::is_same<ValueType, sst::bignum>::value>::type = 0>
ValueType & get_to(NlohmannJson const & src, ValueType & dst);
}
The sst::json::get_to function parses an nlohmann::json value
into dst based on the type of dst and returns dst.
- Integer destinations: (1) (2) (3)
-
Parses
srcintodst.If the internal type of
srcis notinteger_t,unsigned_t,boolean_t, orstring_t, ansst::json::exceptionexception is thrown.For
integer_tandunsigned_t, the parsed value is simply the internal value. Forboolean_t, the parsed values oftrueandfalseare 1 and 0, respectively. Forstring_t, the accepted syntax and parsed value is defined by the following grammar:value:
signopt magnitude
booleansign: one of
+-magnitude:
0
binary-magnitude
octal-magnitude
decimal-magnitude
hexadecimal-magnitudebinary-magnitude:
0bbinary-digit
0Bbinary-digit
binary-magnitude'opt binary-digitoctal-magnitude:
0ooctal-digit
0Ooctal-digit
octal-magnitude'opt octal-digitdecimal-magnitude:
nonzero-decimal-digit
decimal-magnitude'opt decimal-digithexadecimal-magnitude:
0xhexadecimal-digit
0Xhexadecimal-digit
hexadecimal-magnitude'opt hexadecimal-digitbinary-digit: one of
01octal-digit: one of
01234567nonzero-decimal-digit: one of
123456789decimal-digit: one of
0123456789hexadecimal-digit: one of
0123456789
abcdef
ABCDEFboolean: one of
truefalseIf the parsed value cannot be represented by
ValueType, ansst::json::exceptionexception is thrown.
If ValueType is a std::vector-like type, then the internal type of
src must be array_t.
dst will first be cleared, and then each element of the array will be
appended to dst after being parsed by calling sst::json::get_to
recursively.
If ValueType is a std::map-like type, then the internal type of
src must be object_t.
dst will first be cleared, and then each member of the object will be
inserted into dst after being parsed by calling sst::json::get_to
recursively.
If ValueType is any other type, then the parsing will be forwarded to
nlohmann::json’s built-in parsing logic by calling
src.get_to(dst).
In particular, this means that nlohmann::json’s arbitrary
type parsing feature (i.e., user-provided from_json functions) will
work when calling sst::json::get_to.
Except perhaps when parsing is forwarded to nlohmann::json’s
built-in parsing logic, this function will reliably throw an exception
if any kind of error occurs.
In particular, it will throw an exception if ValueType is an integer
type that cannot represent a parsed integer value.
The following functions are provided for parsing JSON object members:
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/json/get_to.hpp[sst/catalog/json/get_to.hpp,window=_blank]>
namespace sst::json {
// (1)
template<class ValueType, class Json>
ValueType & get_to(Json const & src,
typename Json::object_t::key_type const & key,
ValueType & dst) { ... }
// (2)
template<class T, class {cl_nlohmann_json_Json}>
T & get_to({cl_nlohmann_json_Json} const & src,
typename {cl_nlohmann_json_Json}::object_t::key_type const & key,
T & dst,
{cl_sst_undeduced_t}<T> const & default_value);
template<class T, class {cl_nlohmann_json_Json}>
T & get_to({cl_nlohmann_json_Json} const & src,
typename {cl_nlohmann_json_Json}::object_t::key_type const & key,
T & dst,
{cl_sst_undeduced_t}<T> && default_value);
}
The internal type of src must be object_t.
For (1), src must contain a member named key, whose value will be
parsed by calling sst::json::get_to recursively.
For (2), the behavior is the same as (1) except that if src does not
contain a member named key, then dst will be set to default_value.
3.12.5. The sst::json::get_as function
#include <sst/catalog/json/get_as.hpp>
namespace sst::json {
template<class T, class NlohmannJson, class... Args>
T get_as(NlohmannJson & src, typename NlohmannJson::object_t::key_type const & key);
}
3.12.6. The sst::json::remove_to function
#include <sst/catalog/json/remove_to.hpp>
namespace sst::json {
template<class T, class NlohmannJson, class... Args>
T & remove_to(NlohmannJson & src,
typename NlohmannJson::object_t::key_type const & key,
T & dst,
Args &&... args);
}
Calling the sst::json::remove_to function is the same as calling
the sst::json::get_to function with the same parameters, except
key will also be removed from src, if present.
3.12.7. The sst::json::remove_as function
#include <sst/catalog/json/remove_as.hpp>
namespace sst::json {
template<class T, class NlohmannJson, class... Args>
T remove_as(NlohmannJson & src,
typename NlohmannJson::object_t::key_type const & key,
Args &&... args);
}
Calling the sst::json::remove_as function is the same as calling
the sst::json::get_as function with the same parameters, except
key will also be removed from src, if present.
3.12.8. The sst::json::unknown_key function (overload 1)
#include <sst/catalog/json/unknown_key.hpp>
namespace sst::json {
template<class NlohmannJson>
void unknown_key(NlohmannJson const & src);
}
The sst::json::unknown_key function (overload 1) checks for an unknown key in a
JSON object.
If src is a JSON value other than an object, the function throws an
sst::json::exception.
Otherwise, if src does not contain any keys, the function takes no
action.
Otherwise, the function throws an sst::json::exception with a
message that includes at least one of the keys.
This function is intended to be combined with the convention of deleting keys from a JSON object as they are parsed. After all known keys are parsed, any remaining keys are unknown, and calling this function will reject them.
3.12.9. The sst::json::expect_string function
#include <sst/catalog/json/expect_string.hpp>
namespace sst::json {
template<class NlohmannJson>
NlohmannJson const & expect_string(NlohmannJson const & src);
template<class NlohmannJson>
NlohmannJson & expect_string(NlohmannJson & src);
template<class NlohmannJson>
NlohmannJson const &
expect_string(NlohmannJson const & src,
typename NlohmannJson::object_t::key_type const & key);
template<class NlohmannJson>
NlohmannJson & expect_string(NlohmannJson & src,
typename NlohmannJson::object_t::key_type const & key);
}
3.12.10. The sst::json::expect_object function
#include <sst/catalog/json/expect_object.hpp>
namespace sst::json {
template<class NlohmannJson>
NlohmannJson const & expect_object(NlohmannJson const & src);
template<class NlohmannJson>
NlohmannJson & expect_object(NlohmannJson & src);
template<class NlohmannJson>
NlohmannJson const &
expect_object(NlohmannJson const & src,
typename NlohmannJson::object_t::key_type const & key);
template<class NlohmannJson>
NlohmannJson & expect_object(NlohmannJson & src,
typename NlohmannJson::object_t::key_type const & key);
}
3.13. Individual bit access
3.13.1. The sst::get_bit function
#include <sst/bit.h>
namespace sst {
// (1)
template<class X, class Q, class R>
constexpr bool get_bit(X x, Q q, R r) noexcept;
// (2)
template<class X, class R>
constexpr bool get_bit(X x, R r) noexcept;
// (3)
template<class Q, class R>
bool get_bit(void const * x, Q q, R r) noexcept;
// (4)
template<class R>
bool get_bit(void const * x, R r) noexcept;
}
The sst::get_bit function returns the bit at index
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r}\)
of the two’s complement representation of x (for (1) and (2)) or
the region of bytes pointed to by x (for (3) and (4)).
For (1) and (2), the bits of x are zero indexed starting with the
least significant bit (and the most significant bit is the sign bit if
X is signed).
For (3) and (4), the bits of the region of bytes pointed to by x are
zero indexed starting with the least significant bit of the first byte.
X, Q, and R may be any integer types.
If x is a null pointer, q is negative, r is negative, or
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r}\)
is greater than or equal to the number of nonpadding bits in X or the
number of bits in the region of bytes pointed to by x, the behavior is
undefined.
For (2) and (4), q is omitted and taken to be zero.
Prior to C++20, signed integers are permitted to use ones’ complement or sign-magnitude representation instead of two’s complement. This does not affect the behavior of (1) or (2).
3.13.2. The sst::set_bit function
#include <sst/bit.h>
namespace sst {
// (1)
template<class X, class Q, class R>
constexpr X set_bit(X x, Q q, R r, bool b) noexcept;
// (2)
template<class X, class R>
constexpr X set_bit(X x, R r, bool b) noexcept;
// (3)
template<class Q, class R>
void * set_bit(void * x, Q q, R r, bool b) noexcept;
// (4)
template<class R>
void * set_bit(void * x, R r, bool b) noexcept;
}
The sst::set_bit function sets the bit at index
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r}\)
of the two’s complement representation of x (for (1) and (2)) or
the region of bytes pointed to by x (for (3) and (4)) to b.
For (1) and (2), the bits of x are zero indexed starting with the
least significant bit (and the most significant bit is the sign bit if
X is signed), and the function returns the resulting value.
For (3) and (4), the bits of the region of bytes pointed to by x are
zero indexed starting with the least significant bit of the first byte,
and the function returns x.
X, Q, and R may be any integer types.
If x is a null pointer, q is negative, r is negative, or
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r}\)
is greater than or equal to the number of nonpadding bits in X or the
number of bits in the region of bytes pointed to by x, the behavior is
undefined.
For (2) and (4), q is omitted and taken to be zero.
Prior to C++20, signed integers are permitted to use ones’ complement
or sign-magnitude representation instead of two’s complement.
This does not affect the behavior of (1) or (2), except that if the
resulting value cannot be represented by X (i.e., if X is signed,
x is zero, and the most significant bit is being set to 1), the
behavior is undefined.
3.14. Integer packing
3.14.1. The sst::from_bits function
#include <sst/catalog/from_bits.hpp>
// or: <sst/representation.h>
namespace sst {
// (1)
template<class Y, bool SignExtend = std::is_signed<Y>::value,
class Q, class R, class N>
Y from_bits(void const * x, Q q, R r, N n) noexcept;
// (2)
template<class Y, bool SignExtend = std::is_signed<Y>::value,
class R, class N>
Y from_bits(void const * x, R r, N n) noexcept;
}
The sst::from_bits function loads an integer from a sequence of bits
of memory.
First, the n bits of memory starting at bit index
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r}\)
of the region of bytes pointed to by x are interpreted as a two’s
complement integer if SignExtend is true, or as an unsigned integer
if SignExtend is false.
The first bit is taken to be the least significant bit of the integer,
and the last bit is taken to be the most significant bit of the integer
(which is the sign bit if SignExtend is true).
The bits of the region of bytes pointed to by x are zero indexed
starting with the least significant bit of the first byte.
Next, the least significant \(w\) bits of the infinite two’s
complement representation of this integer are considered, where \(w\)
is the number of nonpadding bits in Y.
If Y is signed, these bits are interpreted as a two’s complement
integer (with the most significant bit being the sign bit) and the
resulting value is returned.
If Y is unsigned, these bits are interpreted as an unsigned integer
and the resulting value is returned.
Y, Q, R, and N may be any
integer types.
If x is a null pointer, q is negative, r is negative, n is not
positive, or
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r} + \mathtt{n}\)
is greater than the number of bits in the region of bytes pointed to by
x, the behavior is undefined.
For (2), q is omitted and taken to be zero.
Prior to C++20, signed integers are permitted to use ones’ complement
or sign-magnitude representation instead of two’s complement.
This does not affect the behavior of this function, except that if the
resulting value cannot be represented by Y (i.e., if Y is signed and
the resulting value is \(-2^{1-w}\)), the behavior is undefined.
3.14.2. The sst::to_bits function
#include <sst/catalog/to_bits.hpp>
// or: <sst/representation.h>
namespace sst {
// (1)
template<class Y, bool SignExtend = std::is_signed<Y>::value,
class Q, class R, class N>
void * to_bits(void * x, Q q, R r, Y y, N n) noexcept;
// (2)
template<class Y, bool SignExtend = std::is_signed<Y>::value,
class R, class N>
void * to_bits(void * x, R r, Y y, N n) noexcept;
}
The sst::to_bits function stores an integer to a sequence of bits of
memory.
First, the two’s complement representation of y is considered,
extending it with infinitely many copies of its most significant bit
(which is the sign bit if Y is signed) if SignExtend is true, or
with infinitely many 0’s if SignExtend is false.
Next, the least significant n bits of this infinite representation are
stored to the n bits of memory starting at bit index
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r}\)
of the region of bytes pointed to by x.
The bits of the region of bytes pointed to by x are zero indexed
starting with the least significant bit of the first byte.
Finally, the function returns x.
Y, Q, R, and N may be any
integer types.
If x is a null pointer, q is negative, r is negative, n is not
positive, or
\(\mathtt{q} \cdot \mathtt{CHAR\_BIT} + \mathtt{r} + \mathtt{n}\)
is greater than the number of bits in the region of bytes pointed to by
x, the behavior is undefined.
For (2), q is omitted and taken to be zero.
Prior to C++20, signed integers are permitted to use ones’ complement or sign-magnitude representation instead of two’s complement. This does not affect the behavior of this function.
3.15. Basic algorithms
3.15.1. The sst::min function
#include <sst/catalog/min.hpp>
// or: <sst/algorithm.h>
namespace sst {
template<class T>
constexpr T const & min(T const & a, T const & b);
}
The sst::min function returns a < b ? a : b.
This function was added to the library because std::min is not
constexpr before C++14.
3.15.2. The sst::max function
#include <sst/catalog/max.hpp>
// or: <sst/algorithm.h>
namespace sst {
template<class T>
constexpr T const & max(T const & a, T const & b);
}
The sst::max function returns a < b ? b : a.
This function was added to the library because std::max is not
constexpr before C++14.
3.15.3. The sst::floor_sqrt function
#include <sst/catalog/floor_sqrt.hpp>
// or: <sst/algorithm.h>
namespace sst {
template<std::integral T>
SST_CPP14_CONSTEXPR T floor_sqrt(T x) noexcept;
template<BigInteger T>
T floor_sqrt(T const & x);
template<std::floating_point T>
T floor_sqrt(T x);
}
The sst::floor_sqrt function returns
\(\lfloor\sqrt{\mathtt{x}}\rfloor\).
If x is negative, the behavior is undefined.
3.15.4. The sst::ceil_sqrt function
#include <sst/catalog/ceil_sqrt.hpp>
// or: <sst/algorithm.h>
namespace sst {
template<std::integral T>
SST_CPP14_CONSTEXPR T ceil_sqrt(T x) noexcept;
template<BigInteger T>
T ceil_sqrt(T const & x);
template<std::floating_point T>
T ceil_sqrt(T x);
}
The sst::ceil_sqrt function returns
\(\lceil\sqrt{\mathtt{x}}\rceil\).
If x is negative, the behavior is undefined.
3.15.5. The sst::floor_lg function
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/floor_lg.hpp[sst/catalog/floor_lg.hpp,window=_blank]>
namespace sst {
template<{cl_std_integral} T>
{cl_SST_CPP14_CONSTEXPR} T floor_lg(T x) noexcept;
template<BigInteger T>
T floor_lg(T const & x);
template<{cl_std_floating_point} T>
T floor_lg(T x);
}
The sst::floor_lg function returns
\(\lfloor\lg{\mathtt{x}}\rfloor\).
If x is negative or zero, the behavior is undefined.
3.15.6. The sst::ceil_lg function
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/ceil_lg.hpp[sst/catalog/ceil_lg.hpp,window=_blank]>
namespace sst {
template<{cl_std_integral} T>
{cl_SST_CPP14_CONSTEXPR} T ceil_lg(T x) noexcept;
template<BigInteger T>
T ceil_lg(T const & x);
template<{cl_std_floating_point} T>
T ceil_lg(T x);
}
The sst::ceil_lg function returns
\(\lceil\lg{\mathtt{x}}\rceil\).
If x is negative or zero, the behavior is undefined.
3.16. String utilities
3.16.1. The sst::to_string function
#include <sst/catalog/to_string.hpp>
namespace sst {
// (1)
template<class CharT, class OutputIt, class... Args>
OutputIt to_string(std::basic_string<CharT, Args...> const & src,
OutputIt dst,
bool replace_unrepresentable = false);
// (2)
template<class CharT, class... Args>
std::string to_string(std::basic_string<CharT, Args...> const & src,
bool replace_unrepresentable = false);
// (3)
template<std::integral T, class OutputIt>
OutputIt to_string(T const & src, OutputIt dst);
// (4)
template<std::integral T>
std::string to_string(T const & src);
}
The sst::to_string function converts an object to a string.
3.16.1.1. String sources
Converts one type of string to another.
3.16.1.2. Integer sources
Converts an integer to a string.
3.17. Text encoding utilities
3.17.1. The sst::pick_utf_encoding function
#include <sst/catalog/pick_utf_encoding.hpp>
namespace sst {
template<sst::is_integer_ish T>
constexpr sst::text_encoding pick_utf_encoding() noexcept;
}
The sst::pick_utf_encoding function maps an integer-ish type
T to a UTF encoding via the following algorithm:
-
If
sst::numeric_limits<T>::is_specializedis true:-
If
sst::numeric_limits<T>::min()is negative:-
If the range of
Tis a superset of \(\left[-2^{31},2^{31}\right)\), the result issst::text_encoding::utf_32. -
Otherwise, if the range of
Tis a superset of \(\left[-2^{15},2^{15}\right)\), the result issst::text_encoding::utf_16. -
Otherwise, the result is
sst::text_encoding::utf_8.
-
-
Otherwise:
-
If the range of
Tis a superset of \(\left[0,2^{32}\right)\), the result issst::text_encoding::utf_32. -
Otherwise, if the range of
Tis a superset of \(\left[0,2^{16}\right)\), the result issst::text_encoding::utf_16. -
Otherwise, the result is
sst::text_encoding::utf_8.
-
-
-
Otherwise, the result is
sst::text_encoding::utf_32.
3.17.2. The sst::text_encoding type
#include <sst/catalog/text_encoding.hpp>
namespace sst {
enum class sst::text_encoding {
utf_16,
utf_32,
utf_8,
};
}
3.18. Time utilities
3.18.1. The sst::mono_time function
#include <sst/catalog/mono_time.hpp>
// or: <sst/time.h>
namespace sst {
template<class Duration>
Duration mono_time();
}
The sst::mono_time function returns the current time of an
implementation-defined monotonic clock with respect to Duration.
3.18.2. The sst::mono_time_s function
#include <sst/catalog/mono_time_s.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::mono_time_s_t mono_time_s();
}
The sst::mono_time_s function returns the current time of the
sst::mono_time clock in
seconds.
Note that the return type, sst::mono_time_s_t, is an unspecified
signed integer type with at least 35 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <chrono>
#include <iostream>
#include <sst/catalog/mono_time_s.hpp>
#include <thread>
int main() {
auto const t0 = sst::mono_time_s();
std::this_thread::sleep_for(std::chrono::seconds(1));
auto const t1 = sst::mono_time_s();
std::cout << (t1 - t0) << "\n";
}
g++ a.cpp -lsst ./a.out
1
3.18.3. The sst::mono_time_s_t type
#include <sst/catalog/mono_time_s_t.hpp>
// or: <sst/time.h>
namespace sst {
using mono_time_s_t = std::chrono::seconds::rep;
}
3.18.4. The sst::mono_time_ms function
#include <sst/catalog/mono_time_ms.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::mono_time_ms_t mono_time_ms();
}
The sst::mono_time_ms function returns the current time of the
sst::mono_time clock in
milliseconds.
Note that the return type, sst::mono_time_ms_t, is an unspecified
signed integer type with at least 45 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <chrono>
#include <iostream>
#include <sst/catalog/mono_time_ms.hpp>
#include <thread>
int main() {
auto const t0 = sst::mono_time_ms();
std::this_thread::sleep_for(std::chrono::seconds(1));
auto const t1 = sst::mono_time_ms();
std::cout << (t1 - t0) << "\n";
}
g++ a.cpp -lsst ./a.out
1000
3.18.5. The sst::mono_time_ms_t type
#include <sst/catalog/mono_time_ms_t.hpp>
// or: <sst/time.h>
namespace sst {
using mono_time_ms_t = std::chrono::milliseconds::rep;
}
3.18.6. The sst::mono_time_us function
#include <sst/catalog/mono_time_us.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::mono_time_us_t mono_time_us();
}
The sst::mono_time_us function returns the current time of the
sst::mono_time clock in
microseconds.
Note that the return type, sst::mono_time_us_t, is an unspecified
signed integer type with at least 55 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <chrono>
#include <iostream>
#include <sst/catalog/mono_time_us.hpp>
#include <thread>
int main() {
auto const t0 = sst::mono_time_us();
std::this_thread::sleep_for(std::chrono::seconds(1));
auto const t1 = sst::mono_time_us();
std::cout << (t1 - t0) << "\n";
}
g++ a.cpp -lsst ./a.out
1000149
3.18.7. The sst::mono_time_us_t type
#include <sst/catalog/mono_time_us_t.hpp>
// or: <sst/time.h>
namespace sst {
using mono_time_us_t = std::chrono::microseconds::rep;
}
3.18.8. The sst::mono_time_ns function
#include <sst/catalog/mono_time_ns.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::mono_time_ns_t mono_time_ns();
}
The sst::mono_time_ns function returns the current time of the
sst::mono_time clock in
nanoseconds.
Note that the return type, sst::mono_time_ns_t, is an unspecified
signed integer type with at least 64 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <chrono>
#include <iostream>
#include <sst/catalog/mono_time_ns.hpp>
#include <thread>
int main() {
auto const t0 = sst::mono_time_ns();
std::this_thread::sleep_for(std::chrono::seconds(1));
auto const t1 = sst::mono_time_ns();
std::cout << (t1 - t0) << "\n";
}
g++ a.cpp -lsst ./a.out
1000133270
3.18.9. The sst::mono_time_ns_t type
#include <sst/catalog/mono_time_ns_t.hpp>
// or: <sst/time.h>
namespace sst {
using mono_time_ns_t = std::chrono::nanoseconds::rep;
}
3.18.10. The sst::mono_time_d function
#include <sst/catalog/mono_time_d.hpp>
// or: <sst/time.h>
namespace sst {
inline double mono_time_d();
}
The sst::mono_time_d function returns the current time of the
sst::mono_time clock in
seconds with as much precision as possible.
a.cpp#include <chrono>
#include <iostream>
#include <sst/catalog/mono_time_d.hpp>
#include <thread>
int main() {
auto const t0 = sst::mono_time_d();
std::this_thread::sleep_for(std::chrono::seconds(1));
auto const t1 = sst::mono_time_d();
std::cout << (t1 - t0) << "\n";
}
g++ a.cpp -lsst ./a.out
1.00017
3.18.11. The sst::unix_time function
#include <sst/catalog/unix_time.hpp>
// or: <sst/time.h>
namespace sst {
template<class Duration>
Duration unix_time();
}
The sst::unix_time function returns the current time of the
Unix clock with respect to Duration.
Prior to C++20, this function may use a clock other than the
Unix clock, although there are no known implementations that do so.
For more information, see std::chrono::system_clock or compare
C++17 (N4659) §23.17.7.1 with C++20 (N4860) §27.7.1.1.
3.18.12. The sst::unix_time_s function
#include <sst/catalog/unix_time_s.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::unix_time_s_t unix_time_s();
}
The sst::unix_time_s function returns the current time of the
Unix clock in
seconds.
Note that the return type, sst::unix_time_s_t, is an unspecified
signed integer type with at least 35 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <iostream>
#include <sst/catalog/asctime.hpp>
#include <sst/catalog/gmtime.hpp>
#include <sst/catalog/unix_time_s.hpp>
int main() {
std::cout << sst::asctime(sst::gmtime());
std::cout << sst::unix_time_s() << "\n";
}
g++ a.cpp -lsst ./a.out
Wed Aug 25 05:04:19 2021 1629867859
3.18.13. The sst::unix_time_s_t type
#include <sst/catalog/unix_time_s_t.hpp>
// or: <sst/time.h>
namespace sst {
using unix_time_s_t = std::chrono::seconds::rep;
}
3.18.14. The sst::unix_time_ms function
#include <sst/catalog/unix_time_ms.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::unix_time_ms_t unix_time_ms();
}
The sst::unix_time_ms function returns the current time of the
Unix clock in
milliseconds.
Note that the return type, sst::unix_time_ms_t, is an unspecified
signed integer type with at least 45 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <iostream>
#include <sst/catalog/asctime.hpp>
#include <sst/catalog/gmtime.hpp>
#include <sst/catalog/unix_time_ms.hpp>
int main() {
std::cout << sst::asctime(sst::gmtime());
std::cout << sst::unix_time_ms() << "\n";
}
g++ a.cpp -lsst ./a.out
Wed Aug 25 05:04:19 2021 1629867859036
3.18.15. The sst::unix_time_ms_t type
#include <sst/catalog/unix_time_ms_t.hpp>
// or: <sst/time.h>
namespace sst {
using unix_time_ms_t = std::chrono::milliseconds::rep;
}
3.18.16. The sst::unix_time_us function
#include <sst/catalog/unix_time_us.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::unix_time_us_t unix_time_us();
}
The sst::unix_time_us function returns the current time of the
Unix clock in
microseconds.
Note that the return type, sst::unix_time_us_t, is an unspecified
signed integer type with at least 55 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <iostream>
#include <sst/catalog/asctime.hpp>
#include <sst/catalog/gmtime.hpp>
#include <sst/catalog/unix_time_us.hpp>
int main() {
std::cout << sst::asctime(sst::gmtime());
std::cout << sst::unix_time_us() << "\n";
}
g++ a.cpp -lsst ./a.out
Wed Aug 25 05:04:19 2021 1629867859037931
3.18.17. The sst::unix_time_us_t type
#include <sst/catalog/unix_time_us_t.hpp>
// or: <sst/time.h>
namespace sst {
using unix_time_us_t = std::chrono::microseconds::rep;
}
3.18.18. The sst::unix_time_ns function
#include <sst/catalog/unix_time_ns.hpp>
// or: <sst/time.h>
namespace sst {
inline sst::unix_time_ns_t unix_time_ns();
}
The sst::unix_time_ns function returns the current time of the
Unix clock in
nanoseconds.
Note that the return type, sst::unix_time_ns_t, is an unspecified
signed integer type with at least 64 width bits[6].
For more information, see std::chrono::duration, C++11 (N3337) §20.11.2,
C++14 (N4140) §20.12.2, C++17 (N4659) §23.17.2, or C++20 (N4860) §27.2.
a.cpp#include <iostream>
#include <sst/catalog/asctime.hpp>
#include <sst/catalog/gmtime.hpp>
#include <sst/catalog/unix_time_ns.hpp>
int main() {
std::cout << sst::asctime(sst::gmtime());
std::cout << sst::unix_time_ns() << "\n";
}
g++ a.cpp -lsst ./a.out
Wed Aug 25 05:04:19 2021 1629867859039736561
3.18.19. The sst::unix_time_ns_t type
#include <sst/catalog/unix_time_ns_t.hpp>
// or: <sst/time.h>
namespace sst {
using unix_time_ns_t = std::chrono::nanoseconds::rep;
}
3.18.20. The sst::unix_time_d function
#include <sst/catalog/unix_time_d.hpp>
// or: <sst/time.h>
namespace sst {
inline double unix_time_d();
}
The sst::unix_time_d function returns the current time of the
Unix clock in
seconds with as much precision as possible.
a.cpp#include <iostream>
#include <sst/catalog/asctime.hpp>
#include <sst/catalog/gmtime.hpp>
#include <sst/catalog/unix_time_d.hpp>
int main() {
std::cout << sst::asctime(sst::gmtime());
std::cout << sst::unix_time_d() << "\n";
}
g++ a.cpp -lsst ./a.out
Wed Aug 25 05:04:19 2021 1.62987e+09
3.19. Filesystem tools
3.19.1. The sst::dir_it class
The sst::dir_it class iterates through the contents of
a directory.
#include <sst/catalog/dir_it.hpp>
namespace sst {
class dir_it {
public:
dir_it();
};
}
3.19.1.1. The sst::dir_it constructor (overload 1)
dir_it();
The sst::dir_it constructor (overload 1) creates a
one-past-the-end iterator.
3.19.2. The sst::mkdir function
#include <sst/catalog/mkdir.hpp>
namespace sst {
template<
class Path
sst::enable_if_t<
// TODO
> = 0>
bool mkdir(
Path const & path
);
}
3.19.3. The sst::mkdir_p function
#include <sst/catalog/mkdir_p.hpp>
namespace sst {
template<
class Path
sst::enable_if_t<
// TODO
> = 0>
bool mkdir_p(
Path const & path
);
}
The sst::mkdir_p function ensures that path exists as a
directory by creating any missing components as directories.
3.19.4. The sst::read_whole_file function
The sst::read_whole_file function reads the entire content of a
file.
3.19.4.1. The sst::read_whole_file function (overload 1)
#include <sst/catalog/read_whole_file.hpp>
namespace sst {
template<
class Dst,
sst::enable_if_t<
sst::is_output_iterator<Dst, unsigned char>::value
> = 0
> Dst read_whole_file(
char const * src,
Dst dst
);
}
3.19.4.2. The sst::read_whole_file function (overload 2)
#include <sst/catalog/read_whole_file.hpp>
namespace sst {
template<
class Dst = std::vector<unsigned char>
> Dst read_whole_file(
char const * src
);
}
3.19.5. The sst::write_whole_file function
The sst::write_whole_file function writes a sequence of bytes to a
file, overwriting the file if it already exists.
3.19.5.1. The sst::write_whole_file function (overload 1)
#include <sst/catalog/write_whole_file.hpp>
namespace sst {
template<
class Src,
class End,
sst::enable_if_t<
sst::is_byte_input_iterator<Src>::value
&& sst::is_sentinel<End, Src>::value
> = 0
> void write_whole_file(
Src src,
End const & end,
char const * dst,
sst::write_whole_file_options const & options = {}
);
}
3.19.5.2. The sst::write_whole_file function (overload 2)
#include <sst/catalog/write_whole_file.hpp>
namespace sst {
template<
class Src,
sst::enable_if_t<
sst::is_byte_input_iterable<Src>::value
> = 0
> void write_whole_file(
Src const & src,
char const * dst,
sst::write_whole_file_options const & options = {}
);
}
3.20. SFINAE tools
3.20.1. The sst::enable_t type
#include <sst/catalog/enable_t.hpp>
namespace sst {
using enable_t = int;
}
3.20.2. The sst::enable_if metafunction
#include <sst/catalog/enable_if.hpp>
namespace sst {
template<bool B, class T = sst::enable_t>
struct enable_if : std::enable_if<B, T> {};
template<bool B, class T = sst::enable_t>
using enable_if_t = typename enable_if<B, T>::type;
}
3.20.3. The sst::first_t alias template
#include <sst/catalog/first_t.hpp>
namespace sst {
template<class T, class...>
using first_t = T;
}
The sst::first_t alias template yields its first template
parameter.
3.20.4. SST_COMPILES
#include <sst/catalog/SST_COMPILES.hpp>
#define SST_COMPILES(...) (x)
The SST_COMPILES macro expands to a parenthesized
constant expression (x) that includes the expression
__VA_ARGS__ as an unevaluated operand and always has
value true.
3.20.5. The SST_DEFINE_BOOLEAN_TRAIT_1 macro
#include <sst/catalog/SST_DEFINE_BOOLEAN_TRAIT_1.hpp>
#define SST_DEFINE_BOOLEAN_TRAIT_1(name, T1, expr) \
\
template<class, class = sst::enable_t> \
struct name : std::false_type {}; \
\
template<class T1> \
struct name<T1, typename sst::enable_if<(expr)>::type> \
: std::true_type {};
3.20.6. The SST_DEFINE_BOOLEAN_TRAIT_2 macro
#include <sst/catalog/SST_DEFINE_BOOLEAN_TRAIT_2.hpp>
#define SST_DEFINE_BOOLEAN_TRAIT_2(name, T1, T2, expr) \
\
template<class, class, class = sst::enable_t> \
struct name : std::false_type {}; \
\
template<class T1, class T2> \
struct name<T1, T2, typename sst::enable_if<(expr)>::type> \
: std::true_type {};
3.20.7. sst::dependent_true
#include <sst/catalog/dependent_true.hpp>
namespace sst {
template<class...>
struct dependent_true
: std::integral_constant<bool, v> {};
}
The sst::dependent_true trait defines v to true.
This is useful when the constant value true is needed but
must be made dependent on one or more template parameters to delay
evaluation.
3.20.8. sst::dependent_false
#include <sst/catalog/dependent_false.hpp>
namespace sst {
template<class...>
struct dependent_false
: std::integral_constant<bool, v> {};
}
The sst::dependent_false trait defines v to false.
This is useful when the constant value false is needed but
must be made dependent on one or more template parameters to delay
evaluation.
3.21. Synchronization utilities
3.21.1. The sst::cooldown_mutex class
#include <sst/catalog/cooldown_mutex.hpp>
namespace sst {
class cooldown_mutex;
}
The sst::cooldown_mutex class provides a mutex that, after being
unlocked, cannot be locked again until a specified amount of time,
called the cooldown, has passed.
The cooldown does not apply to the first lock, i.e., after the mutex is
constructed, it can be locked immediately.
3.21.2. The sst::atomic_shared_ptr class
#include <sst/catalog/atomic_shared_ptr.hpp>
namespace sst {
template<class T>
class atomic_shared_ptr final {
public:
atomic_shared_ptr() = default;
~atomic_shared_ptr() = default;
atomic_shared_ptr(atomic_shared_ptr const &) = delete;
atomic_shared_ptr(atomic_shared_ptr &&) = delete;
void operator=(atomic_shared_ptr const &) = delete;
void operator=(atomic_shared_ptr &&) = delete;
atomic_shared_ptr(std::shared_ptr<T> const & ptr);
void operator=(std::shared_ptr<T> const & ptr);
operator std::shared_ptr<T>() const;
void store(std::shared_ptr<T> const & ptr,
std::memory_order mo = std::memory_order_seq_cst);
std::shared_ptr<T>
load(std::memory_order mo = std::memory_order_seq_cst) const;
};
}
The sst::atomic_shared_ptr class is an atomic wrapper for the
std::shared_ptr class.
This class was added to the library because
std::atomic<std::shared_ptr> is not available before C++20.
3.22. Random number utilities
3.22.1. The sstByteRng requirement
sstByteRng requirement
A type G satisfies the sstByteRng requirement if all of the
following hold:
-
Gsatisfies theUniformRandomBitGeneratorrequirement. -
G::result_typeisunsigned char. -
G::min()is zero. -
G::max()issst::uchar_max_v. -
If
gis an object of typeG,pis an output iterator that acceptsunsigned char, andnis a nonnegative integer, then the expressiong(p, n)writesnrandom bytes topand returns the updatedp.This functionality can always be implemented using
operator()()as follows:template<class P, class N> P operator()(P p, N n) { while (n) { *p = operator()(); ++p; --n; } return p; }However, it is typical that
Gwill provide an implementation with higher performance.
3.22.2. The sstCryptoRng requirement
A type G satisfies the sstCryptoRng requirement if all of the
following hold:
-
Gsatisfies theUniformRandomBitGeneratorrequirement. -
If
gis an object of typeG, then the sequence of all random values produced by any overload ofg’soperator()function throughoutg’s lifetime is cryptographically secure.
3.22.3. The sst::crypto_rng function
3.22.3.1. Synopsis
#include <sst/catalog/crypto_rng.hpp>
namespace sst {
// Overload 1
sst::crypto_rng_t & crypto_rng();
// Overload 2
template<class... Args, sst::enable_if_t<(sizeof...(Args) > 0)> = 0>
R crypto_rng(Args &&... args);
}
3.22.3.2. Overload 1
#include <sst/catalog/crypto_rng.hpp>
namespace sst {
sst::crypto_rng_t & crypto_rng();
}
The sst::crypto_rng function (overload 1) returns a reference to a
cryptographically secure random number generator g with
thread storage duration.
Because the type of g, sst::crypto_rng_t, satisfies the
sstCryptoRng requirement and the sstCryptoRng requirement
is a superset of the UniformRandomBitGenerator requirement, g
can be used in most situations where a standard random number generator,
such as one of type std::random_device or std::mt19937, can
be used.
Because g has thread storage duration, data races can be avoided
regardless of multithreading by simply calling sst::crypto_rng()
in every situation where a random number generator is needed.
sst-example-45.cpp#include <iostream>
#include <random>
#include <sst/catalog/crypto_rng.hpp>
int main() {
std::uniform_int_distribution<int> d(1, 100);
std::cout << "Here is a random integer between ";
std::cout << d.min() << " and " << d.max() << ": ";
std::cout << d(sst::crypto_rng()) << "\n";
}
3.22.3.3. Overload 2
#include <sst/catalog/crypto_rng.hpp>
namespace sst {
template<
class... Args,
sst::enable_if_t<
(sizeof...(Args) > 0U)
> = 0>
auto crypto_rng(Args &&... args)
-> decltype(sst::crypto_rng()(std::forward<Args>(args)...));
}
The sst::crypto_rng function (overload 2) is a convenience overload that is
equivalent to
sst::crypto_rng()(std::forward<Args>(args)...).
The following program uses sst::crypto_rng (overload 2) to generate
16 random bytes.
sst-example-46.cpp#include <iostream>
#include <vector>
#include <sst/catalog/crypto_rng.hpp>
#include <sst/catalog/to_hex.hpp>
int main() {
std::vector<unsigned char> v(16);
sst::crypto_rng(v.data(), v.size());
std::cout << sst::to_hex(v) << "\n";
return 0;
}
g++ sst-example-46.cpp -lsst
C4A3928E075C6536E9DA51DEC9B7F392
3.22.4. The sst::crypto_rng_t type
#include <sst/catalog/crypto_rng_t.hpp>
namespace sst {
using crypto_rng_t = G;
}
The sst::crypto_rng_t type is an implementation-defined type G
that satisfies the sstByteRng and sstCryptoRng
requirements.
3.22.5. The sst::openssl_rand_bytes_rng class
#include <sst/catalog/openssl_rand_bytes_rng.hpp>
namespace sst {
#if SST_WITH_OPENSSL_CRYPTO
class openssl_rand_bytes_rng final {
public:
using result_type = unsigned char;
static constexpr unsigned char min() noexcept {
return 0;
}
static constexpr unsigned char max() noexcept {
return sst::type_max<unsigned char>::value;
}
template<std::integral Size>
explicit openssl_rand_bytes_rng(Size n);
openssl_rand_bytes_rng();
openssl_rand_bytes_rng(openssl_rand_bytes_rng &&) noexcept;
openssl_rand_bytes_rng(openssl_rand_bytes_rng const &) = delete;
openssl_rand_bytes_rng & operator=(openssl_rand_bytes_rng const &) = delete;
openssl_rand_bytes_rng & operator=(openssl_rand_bytes_rng &&) = delete;
~openssl_rand_bytes_rng() noexcept;
void refill(bool eager = true);
unsigned char operator()();
template<class OutputIt, std::integral Size>
OutputIt operator()(OutputIt dst, Size n);
};
#endif
}
3.23. Container utilities
3.23.1. The sst::checked_reserve function
#include <sst/catalog/checked_reserve.hpp>
namespace sst {
template<linkhttps://en.cppreference.com/w/cpp/container[Container] C, std::integral Size>
void checked_reserve(C & container, Size const size);
}
The sst::checked_reserve function is equivalent to calling
container.reserve(size), except that if size cannot be represented
by typename C::size_type, an sst::checked_overflow will
be thrown.
3.23.2. The sst::checked_resize function
#include <sst/catalog/checked_resize.hpp>
namespace sst {
template<linkhttps://en.cppreference.com/w/cpp/container[Container] C, std::integral Size>
void checked_resize(C & container, Size const size);
}
The sst::checked_resize function is equivalent to calling
container.resize(size), except that if size cannot be represented by
typename C::size_type, an sst::checked_overflow will be
thrown.
3.24. Networking utilities
3.24.1. The sst::socket class
3.24.1.1. Synopsis
#include <sst/catalog/socket.hpp>
namespace sst {
class socket {
public:
};
}
3.24.1.3. Examples
#include <future>
#include <iostream>
#include <ostream>
#include <string>
#include <sst/catalog/socket.hpp>
#include <sst/catalog/socket_shutdown.hpp>
int main(int argc, char ** argv) {
// Initialize the socket library, if necessary.
sst::socket_library_scope socket_library_scope;
sst::socket socket;
if (argc > 1) {
// Run as the server if there's a command-line argument.
sst::socket listener;
listener.reuseaddr(true);
listener.listen("127.0.0.1", 12345);
socket = listener.accept();
} else {
// Run as the client if there's no command-line argument.
socket.connect("127.0.0.1", 12345);
}
// In a background thread, read data from standard input and send it
// over the socket.
auto background = std::async(std::launch::async, [&socket] {
std::string line;
while (std::getline(std::cin, line)) {
line += '\n';
socket.send_exactly(&line[0], line.size());
}
socket.shutdown(sst::socket_shutdown::send());
});
// In the main thread, receive data from the socket and write it to
// standard output.
std::string buf;
while (!socket.eof()) {
buf.resize(100);
auto const n = socket.recv_some(&buf[0], buf.size());
buf.resize(n);
std::cout << buf << std::flush;
}
// Wait for the background thread to finish.
background.get();
}
3.24.2. The sst::socket_library_scope type
#include <sst/catalog/socket_library_scope.hpp>
namespace sst {
using socket_library_scope = implementation-defined;
}
The sst::socket_library_scope type can be used to initialize and
shut down the underlying socket library, if the library requires it
(e.g., Winsock).
When an sst::socket_library_scope object is constructed without
arguments, it initializes the underlying socket library, throwing an
exception if an error occurs.
When the object is destructed, it shuts down the underlying socket
library, ignoring any errors.
If the underlying socket library does not require any initialization or
shutting down, the sst::socket_library_scope constructor and
destructor are noops.
sst-example-47.cpp#include <iostream>
#include <sst/catalog/socket.hpp>
#include <sst/catalog/socket_library_scope.hpp>
int main() {
sst::socket_library_scope scope;
std::cout << "Connecting to www.stealthsoftwareinc.com.\n";
sst::socket s;
s.connect("www.stealthsoftwareinc.com", 443);
std::cout << "Connected.\n";
}
g++ sst-example-47.cpp -lsst
Connecting to www.stealthsoftwareinc.com.
Connected.
3.24.3. The sst::socket_poll_set class
#include <sst/catalog/socket_poll_set.hpp>
namespace sst {
using socket_poll_set = implementation-defined;
}
This example implements an echo server.
sst-example-48.cpp#include <cstring>
#include <iostream>
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include <sst/catalog/socket.hpp>
#include <sst/catalog/socket_library_scope.hpp>
#include <sst/catalog/socket_poll_set.hpp>
#include <sst/catalog/socket_shutdown.hpp>
// TODO: Handle socket exceptions better.
int main() {
sst::socket_library_scope socket_library_scope;
sst::socket listener;
listener.listen(12345);
sst::socket_poll_set poll_set;
poll_set.insert(&listener);
struct context_t {
sst::socket socket;
std::vector<unsigned char> buf;
std::vector<unsigned char>::size_type len = 0;
context_t() : buf(1024) {
}
};
std::map<sst::socket *, std::unique_ptr<context_t>> ctxs;
while (true) {
poll_set.poll();
for (auto const & entry : poll_set) {
if (&entry.socket() == &listener) {
if (entry.can_recv()) {
std::unique_ptr<context_t> ctx;
{
sst::socket s = entry.socket().accept();
ctx.reset(new context_t);
ctx->socket = std::move(s);
}
sst::socket & s = ctx->socket;
s.blocking(false);
ctxs.emplace(&s, std::move(ctx));
poll_set.insert(&s);
}
continue;
}
context_t & ctx = *ctxs[&entry.socket()];
if (entry.can_recv()) {
ctx.len += ctx.socket.recv_some(&ctx.buf[ctx.len],
ctx.buf.size() - ctx.len);
}
if (entry.can_send()) {
auto const n = ctx.socket.send_some(&ctx.buf[0], ctx.len);
std::memmove(&ctx.buf[0], &ctx.buf[n], ctx.len - n);
ctx.len -= n;
if (ctx.len == 0) {
ctx.len += ctx.socket.recv_some(&ctx.buf[ctx.len],
ctx.buf.size() - ctx.len);
if (ctx.socket.eof()) {
poll_set.erase(&ctx.socket);
ctx.socket.shutdown(sst::socket_shutdown::both());
ctx.socket.close();
ctxs.erase(&ctx.socket);
}
}
}
}
}
}
g++ sst-example-48.cpp -lsst
3.25. Windows utilities
3.25.1. The sst::gle_error_string function
#include <sst/catalog/gle_error_string.hpp>
namespace sst {
#if SST_WITH_WINDOWS_KERNEL32
std::string gle_error_string(sst_w32_DWORD code);
#endif
}
The sst::gle_error_string function returns a string representing
the GetLastError code code.
3.25.2. The sst::gle_exception class
#include <sst/catalog/gle_exception.hpp>
namespace sst {
class gle_exception : public std::runtime_error {
public:
explicit gle_exception(std::string const & message,
sst_w32_DWORD code);
explicit gle_exception(char const * message, sst_w32_DWORD code);
explicit gle_exception(std::string const & message);
explicit gle_exception(char const * message);
explicit gle_exception(sst_w32_DWORD code);
explicit gle_exception();
sst_w32_DWORD code() const noexcept;
};
}
If message is a null pointer, the behavior is undefined.
Otherwise, if message is empty, it will be adjusted to
sst::gle_error_string(code) + ".".
Otherwise, if message is a function name, it will be adjusted to
message + "() failed: " + sst::gle_error_string(code) + ".".
Otherwise, message will be adjusted to
message + ": " + sst::gle_error_string(code) + ".".
Omitting code is equivalent to passing GetLastError().
3.25.3. The sst_w32_accept function
#include <sst/catalog/sst_w32_accept.h>
#if SST_WITH_WINDOWS_WS2_32
sst_w32_SOCKET sst_w32_accept(
sst_w32_SOCKET s,
sst_w32_SOCKADDR * addr,
int * addrlen
);
#endif
The sst_w32_accept function is equivalent to the
accept function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.4. The sst_w32_ADDRESS_FAMILY type
#include <sst/catalog/sst_w32_ADDRESS_FAMILY.h>
#if SST_WITH_WINDOWS_WS2_32
typedef ADDRESS_FAMILY sst_w32_ADDRESS_FAMILY;
#endif
The sst_w32_ADDRESS_FAMILY type is equivalent to the
ADDRESS_FAMILY type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.5. The sst_w32_ADDRINFOA type
#include <sst/catalog/sst_w32_ADDRINFOA.h>
#if SST_WITH_WINDOWS_WS2_32
typedef ADDRINFOA sst_w32_ADDRINFOA;
#endif
The sst_w32_ADDRINFOA type is equivalent to the
ADDRINFOA type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.6. The sst_w32_ADDRINFOA_unwrap function
#include <sst/catalog/sst_w32_ADDRINFOA_unwrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_ADDRINFOA_unwrap(
sst_w32_ADDRINFOA_wrapper const * src,
sst_w32_ADDRINFOA * dst
);
#endif
The sst_w32_ADDRINFOA_unwrap function converts an sst_w32_ADDRINFOA_wrapper to an
sst_w32_ADDRINFOA.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.7. The sst_w32_ADDRINFOA_wrap function
#include <sst/catalog/sst_w32_ADDRINFOA_wrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_ADDRINFOA_wrap(
sst_w32_ADDRINFOA const * src,
sst_w32_ADDRINFOA_wrapper * dst
);
#endif
The sst_w32_ADDRINFOA_wrap function converts an sst_w32_ADDRINFOA to an
sst_w32_ADDRINFOA_wrapper.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.8. The sst_w32_ADDRINFOA_wrapper type
#include <sst/catalog/sst_w32_ADDRINFOA_wrapper.h>
#if SST_WITH_WINDOWS_WS2_32
typedef struct sst_w32_ADDRINFOA_wrapper {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
char * ai_canonname;
sst_w32_SOCKADDR * ai_addr;
sst_w32_ADDRINFOA * ai_next;
} sst_w32_ADDRINFOA_wrapper;
#endif
The sst_w32_ADDRINFOA_wrapper type wraps the
ADDRINFOA type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
The sst_w32_ADDRINFOA_wrap and sst_w32_ADDRINFOA_unwrap functions can be used to
convert back and forth between the ADDRINFOA and
sst_w32_ADDRINFOA_wrapper types.
The types do not necessarily have the same ABI, so they cannot be
type punned.
3.25.9. The SST_W32_AF_INET constant
#include <sst/catalog/SST_W32_AF_INET.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_AF_INET (AF_INET)
#endif
The SST_W32_AF_INET constant is equivalent to the
AF_INET constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.10. The SST_W32_AF_INET6 constant
#include <sst/catalog/SST_W32_AF_INET6.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_AF_INET6 (AF_INET6)
#endif
The SST_W32_AF_INET6 constant is equivalent to the
AF_INET6 constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.11. The SST_W32_AF_UNSPEC constant
#include <sst/catalog/SST_W32_AF_UNSPEC.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_AF_UNSPEC (AF_UNSPEC)
#endif
The SST_W32_AF_UNSPEC constant is equivalent to the
AF_UNSPEC constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.12. The SST_W32_AI_PASSIVE constant
#include <sst/catalog/SST_W32_AI_PASSIVE.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_AI_PASSIVE (AI_PASSIVE)
#endif
The SST_W32_AI_PASSIVE constant is equivalent to the
AI_PASSIVE constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.13. The sst_w32_bind function
#include <sst/catalog/sst_w32_bind.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_bind(
sst_w32_SOCKET s,
sst_w32_SOCKADDR const * name,
int namelen
);
#endif
The sst_w32_bind function is equivalent to the
bind function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.14. The sst_w32_CHAR type
#include <sst/catalog/sst_w32_CHAR.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef CHAR sst_w32_CHAR;
#endif
The sst_w32_CHAR type is equivalent to the
CHAR type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.15. The sst_w32_closesocket function
#include <sst/catalog/sst_w32_closesocket.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_closesocket(
sst_w32_SOCKET s
);
#endif
The sst_w32_closesocket function is equivalent to the
closesocket function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.16. The sst_w32_connect function
#include <sst/catalog/sst_w32_connect.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_connect(
sst_w32_SOCKET s,
sst_w32_SOCKADDR const * name,
int namelen
);
#endif
The sst_w32_connect function is equivalent to the
connect function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.17. The sst_w32_DWORD type
#include <sst/catalog/sst_w32_DWORD.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef DWORD sst_w32_DWORD;
#endif
The sst_w32_DWORD type is equivalent to the
DWORD type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.18. The SST_W32_FIONBIO constant
#include <sst/catalog/SST_W32_FIONBIO.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_FIONBIO (FIONBIO)
#endif
The SST_W32_FIONBIO constant is equivalent to the
FIONBIO constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.19. The sst_w32_freeaddrinfo function
#include <sst/catalog/sst_w32_freeaddrinfo.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_freeaddrinfo(
sst_w32_ADDRINFOA * pAddrInfo
);
#endif
The sst_w32_freeaddrinfo function is equivalent to the
freeaddrinfo function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.20. The sst_w32_getaddrinfo function
#include <sst/catalog/sst_w32_getaddrinfo.h>
#if SST_WITH_WINDOWS_WS2_32
sst_w32_INT sst_w32_getaddrinfo(
char const * pNodeName,
char const * pServiceName,
sst_w32_ADDRINFOA const * pHints,
sst_w32_ADDRINFOA ** ppResult
);
#endif
The sst_w32_getaddrinfo function is equivalent to the
getaddrinfo function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.21. The sst_w32_getsockname function
#include <sst/catalog/sst_w32_getsockname.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_getsockname(
sst_w32_SOCKET s,
sst_w32_SOCKADDR * name,
int * namelen
);
#endif
The sst_w32_getsockname function is equivalent to the
getsockname function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.22. The sst_w32_getsockopt function
#include <sst/catalog/sst_w32_getsockopt.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_getsockopt(
sst_w32_SOCKET s,
int level,
int optname,
char * optval,
int * optlen
);
#endif
The sst_w32_getsockopt function is equivalent to the
getsockopt function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.23. The SST_W32_INET_ADDRSTRLEN constant
#include <sst/catalog/SST_W32_INET_ADDRSTRLEN.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_INET_ADDRSTRLEN (INET_ADDRSTRLEN)
#endif
The SST_W32_INET_ADDRSTRLEN constant is equivalent to the
INET_ADDRSTRLEN constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.24. The sst_w32_inet_ntop function
#include <sst/catalog/sst_w32_inet_ntop.h>
#if SST_WITH_WINDOWS_WS2_32
sst_w32_PCSTR sst_w32_inet_ntop(
sst_w32_INT Family,
sst_w32_VOID const * pAddr,
sst_w32_PSTR pStringBuf,
size_t StringBufSize
);
#endif
The sst_w32_inet_ntop function is equivalent to the
inet_ntop function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.25. The SST_W32_INET6_ADDRSTRLEN constant
#include <sst/catalog/SST_W32_INET6_ADDRSTRLEN.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_INET6_ADDRSTRLEN (INET6_ADDRSTRLEN)
#endif
The SST_W32_INET6_ADDRSTRLEN constant is equivalent to the
INET6_ADDRSTRLEN constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.26. The sst_w32_INT type
#include <sst/catalog/sst_w32_INT.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef INT sst_w32_INT;
#endif
The sst_w32_INT type is equivalent to the
INT type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.27. The SST_W32_INVALID_SOCKET constant
#include <sst/catalog/SST_W32_INVALID_SOCKET.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_INVALID_SOCKET (INVALID_SOCKET)
#endif
The SST_W32_INVALID_SOCKET constant is equivalent to the
INVALID_SOCKET constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.28. The sst_w32_ioctlsocket function
#include <sst/catalog/sst_w32_ioctlsocket.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_ioctlsocket(
sst_w32_SOCKET s,
long cmd,
sst_w32_u_long * argp
);
#endif
The sst_w32_ioctlsocket function is equivalent to the
ioctlsocket function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.29. The SST_W32_IPPROTO_TCP constant
#include <sst/catalog/SST_W32_IPPROTO_TCP.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_IPPROTO_TCP (IPPROTO_TCP)
#endif
The SST_W32_IPPROTO_TCP constant is equivalent to the
IPPROTO_TCP constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.30. The SST_W32_IPPROTO_UDP constant
#include <sst/catalog/SST_W32_IPPROTO_UDP.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_IPPROTO_UDP (IPPROTO_UDP)
#endif
The SST_W32_IPPROTO_UDP constant is equivalent to the
IPPROTO_UDP constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.31. The sst_w32_LANGID type
#include <sst/catalog/sst_w32_LANGID.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef LANGID sst_w32_LANGID;
#endif
The sst_w32_LANGID type is equivalent to the
LANGID type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.32. The sst_w32_listen function
#include <sst/catalog/sst_w32_listen.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_listen(
sst_w32_SOCKET s,
int backlog
);
#endif
The sst_w32_listen function is equivalent to the
listen function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.33. The sst_w32_ntohl function
#include <sst/catalog/sst_w32_ntohl.h>
#if SST_WITH_WINDOWS_WS2_32
sst_w32_u_long sst_w32_ntohl(
sst_w32_u_long netlong
);
#endif
The sst_w32_ntohl function is equivalent to the
ntohl function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.34. The sst_w32_ntohs function
#include <sst/catalog/sst_w32_ntohs.h>
#if SST_WITH_WINDOWS_WS2_32
sst_w32_u_short sst_w32_ntohs(
sst_w32_u_short netshort
);
#endif
The sst_w32_ntohs function is equivalent to the
ntohs function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.35. The sst_w32_offsetof_SOCKADDR_STORAGE_ss_family constant
#include <sst/catalog/sst_w32_offsetof_SOCKADDR_STORAGE_ss_family.h>
#if SST_WITH_WINDOWS_WS2_32
size_t const sst_w32_offsetof_SOCKADDR_STORAGE_ss_family = offsetof(SOCKADDR_STORAGE, ss_family);
#endif
The sst_w32_offsetof_SOCKADDR_STORAGE_ss_family constant is equivalent to the
offsetof(SOCKADDR_STORAGE, ss_family) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.36. The sst_w32_PCSTR type
#include <sst/catalog/sst_w32_PCSTR.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef PCSTR sst_w32_PCSTR;
#endif
The sst_w32_PCSTR type is equivalent to the
PCSTR type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.37. The SST_W32_POLLRDBAND constant
#include <sst/catalog/SST_W32_POLLRDBAND.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_POLLRDBAND (POLLRDBAND)
#endif
The SST_W32_POLLRDBAND constant is equivalent to the
POLLRDBAND constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.38. The SST_W32_POLLRDNORM constant
#include <sst/catalog/SST_W32_POLLRDNORM.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_POLLRDNORM (POLLRDNORM)
#endif
The SST_W32_POLLRDNORM constant is equivalent to the
POLLRDNORM constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.39. The SST_W32_POLLWRNORM constant
#include <sst/catalog/SST_W32_POLLWRNORM.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_POLLWRNORM (POLLWRNORM)
#endif
The SST_W32_POLLWRNORM constant is equivalent to the
POLLWRNORM constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.40. The sst_w32_PSTR type
#include <sst/catalog/sst_w32_PSTR.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef PSTR sst_w32_PSTR;
#endif
The sst_w32_PSTR type is equivalent to the
PSTR type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.41. The sst_w32_recv function
#include <sst/catalog/sst_w32_recv.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_recv(
sst_w32_SOCKET s,
char * buf,
int len,
int flags
);
#endif
The sst_w32_recv function is equivalent to the
recv function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.42. The SST_W32_SD_BOTH constant
#include <sst/catalog/SST_W32_SD_BOTH.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SD_BOTH (SD_BOTH)
#endif
The SST_W32_SD_BOTH constant is equivalent to the
SD_BOTH constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.43. The SST_W32_SD_RECEIVE constant
#include <sst/catalog/SST_W32_SD_RECEIVE.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SD_RECEIVE (SD_RECEIVE)
#endif
The SST_W32_SD_RECEIVE constant is equivalent to the
SD_RECEIVE constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.44. The SST_W32_SD_SEND constant
#include <sst/catalog/SST_W32_SD_SEND.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SD_SEND (SD_SEND)
#endif
The SST_W32_SD_SEND constant is equivalent to the
SD_SEND constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.45. The sst_w32_send function
#include <sst/catalog/sst_w32_send.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_send(
sst_w32_SOCKET s,
char const * buf,
int len,
int flags
);
#endif
The sst_w32_send function is equivalent to the
send function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.46. The sst_w32_setsockopt function
#include <sst/catalog/sst_w32_setsockopt.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_setsockopt(
sst_w32_SOCKET s,
int level,
int optname,
const char * optval,
int optlen
);
#endif
The sst_w32_setsockopt function is equivalent to the
setsockopt function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.47. The sst_w32_SHORT type
#include <sst/catalog/sst_w32_SHORT.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef SHORT sst_w32_SHORT;
#endif
The sst_w32_SHORT type is equivalent to the
SHORT type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.48. The sst_w32_shutdown function
#include <sst/catalog/sst_w32_shutdown.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_shutdown(
sst_w32_SOCKET s,
int how
);
#endif
The sst_w32_shutdown function is equivalent to the
shutdown function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.49. The SST_W32_SIZEOF_ADDRINFOA constant
#include <sst/catalog/SST_W32_SIZEOF_ADDRINFOA.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SIZEOF_ADDRINFOA (/*...*/)
#endif
The SST_W32_SIZEOF_ADDRINFOA constant is equivalent to the
sizeof(ADDRINFOA) constant from the Windows
API, except it can also be used in the preprocessor, where it is an unsigned integer.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.50. The sst_w32_sizeof_SOCKADDR_IN constant
#include <sst/catalog/sst_w32_sizeof_SOCKADDR_IN.h>
#if SST_WITH_WINDOWS_WS2_32
size_t const sst_w32_sizeof_SOCKADDR_IN = sizeof(sockaddr_in);
#endif
The sst_w32_sizeof_SOCKADDR_IN constant is equivalent to the
sizeof(sockaddr_in) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.51. The sst_w32_sizeof_SOCKADDR_IN6 constant
#include <sst/catalog/sst_w32_sizeof_SOCKADDR_IN6.h>
#if SST_WITH_WINDOWS_WS2_32
size_t const sst_w32_sizeof_SOCKADDR_IN6 = sizeof(sockaddr_in6);
#endif
The sst_w32_sizeof_SOCKADDR_IN6 constant is equivalent to the
sizeof(sockaddr_in6) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.52. The sst_w32_sizeof_SOCKADDR_STORAGE constant
#include <sst/catalog/sst_w32_sizeof_SOCKADDR_STORAGE.h>
#if SST_WITH_WINDOWS_WS2_32
size_t const sst_w32_sizeof_SOCKADDR_STORAGE = sizeof(SOCKADDR_STORAGE);
#endif
The sst_w32_sizeof_SOCKADDR_STORAGE constant is equivalent to the
sizeof(SOCKADDR_STORAGE) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.53. The SST_W32_SOCKET_ERROR constant
#include <sst/catalog/SST_W32_SOCKET_ERROR.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SOCKET_ERROR (POLLRDBAND)
#endif
The SST_W32_SOCKET_ERROR constant is equivalent to the
POLLRDBAND constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.54. The sst_w32_sizeof_WIN32_FILE_ATTRIBUTE_DATA constant
#include <sst/catalog/sst_w32_sizeof_WIN32_FILE_ATTRIBUTE_DATA.h>
#if SST_WITH_WINDOWS_KERNEL32
size_t const sst_w32_sizeof_WIN32_FILE_ATTRIBUTE_DATA = sizeof(WIN32_FILE_ATTRIBUTE_DATA);
#endif
The sst_w32_sizeof_WIN32_FILE_ATTRIBUTE_DATA constant is equivalent to the
sizeof(WIN32_FILE_ATTRIBUTE_DATA) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.55. The sst_w32_sizeof_WIN32_FIND_DATAA constant
#include <sst/catalog/sst_w32_sizeof_WIN32_FIND_DATAA.h>
#if SST_WITH_WINDOWS_KERNEL32
size_t const sst_w32_sizeof_WIN32_FIND_DATAA = sizeof(WIN32_FIND_DATAA);
#endif
The sst_w32_sizeof_WIN32_FIND_DATAA constant is equivalent to the
sizeof(WIN32_FIND_DATAA) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.56. The sst_w32_sizeof_WIN32_FIND_DATAW constant
#include <sst/catalog/sst_w32_sizeof_WIN32_FIND_DATAW.h>
#if SST_WITH_WINDOWS_KERNEL32
size_t const sst_w32_sizeof_WIN32_FIND_DATAW = sizeof(WIN32_FIND_DATAW);
#endif
The sst_w32_sizeof_WIN32_FIND_DATAW constant is equivalent to the
sizeof(WIN32_FIND_DATAW) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.57. The sst_w32_sizeof_WSADATA constant
#include <sst/catalog/sst_w32_sizeof_WSADATA.h>
#if SST_WITH_WINDOWS_WS2_32
size_t const sst_w32_sizeof_WSADATA = sizeof(WSADATA);
#endif
The sst_w32_sizeof_WSADATA constant is equivalent to the
sizeof(WSADATA) constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.58. The SST_W32_SIZEOF_WSAPOLLFD constant
#include <sst/catalog/SST_W32_SIZEOF_WSAPOLLFD.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SIZEOF_WSAPOLLFD (/*...*/)
#endif
The SST_W32_SIZEOF_WSAPOLLFD constant is equivalent to the
sizeof(WSAPOLLFD) constant from the Windows
API, except it can also be used in the preprocessor, where it is an unsigned integer.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.59. The SST_W32_SO_REUSEADDR constant
#include <sst/catalog/SST_W32_SO_REUSEADDR.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SO_REUSEADDR (SO_REUSEADDR)
#endif
The SST_W32_SO_REUSEADDR constant is equivalent to the
SO_REUSEADDR constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.60. The SST_W32_SOCK_DGRAM constant
#include <sst/catalog/SST_W32_SOCK_DGRAM.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SOCK_DGRAM (SOCK_DGRAM)
#endif
The SST_W32_SOCK_DGRAM constant is equivalent to the
SOCK_DGRAM constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.61. The SST_W32_SOCK_STREAM constant
#include <sst/catalog/SST_W32_SOCK_STREAM.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SOCK_STREAM (SOCK_STREAM)
#endif
The SST_W32_SOCK_STREAM constant is equivalent to the
SOCK_STREAM constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.62. The sst_w32_SOCKADDR type
#include <sst/catalog/sst_w32_SOCKADDR.h>
#if SST_WITH_WINDOWS_WS2_32
typedef sockaddr sst_w32_SOCKADDR;
#endif
The sst_w32_SOCKADDR type is equivalent to the
sockaddr type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.63. The sst_w32_SOCKADDR_IN type
#include <sst/catalog/sst_w32_SOCKADDR_IN.h>
#if SST_WITH_WINDOWS_WS2_32
typedef sockaddr_in sst_w32_SOCKADDR_IN;
#endif
The sst_w32_SOCKADDR_IN type is equivalent to the
sockaddr_in type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.64. The sst_w32_SOCKADDR_IN_unwrap function
#include <sst/catalog/sst_w32_SOCKADDR_IN_unwrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_SOCKADDR_IN_unwrap(
sst_w32_SOCKADDR_IN_wrapper const * src,
sst_w32_SOCKADDR_IN * dst
);
#endif
The sst_w32_SOCKADDR_IN_unwrap function converts an sst_w32_SOCKADDR_IN_wrapper to an
sst_w32_SOCKADDR_IN.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.65. The sst_w32_SOCKADDR_IN_wrap function
#include <sst/catalog/sst_w32_SOCKADDR_IN_wrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_SOCKADDR_IN_wrap(
sst_w32_SOCKADDR_IN const * src,
sst_w32_SOCKADDR_IN_wrapper * dst
);
#endif
The sst_w32_SOCKADDR_IN_wrap function converts an sst_w32_SOCKADDR_IN to an
sst_w32_SOCKADDR_IN_wrapper.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.66. The sst_w32_SOCKADDR_IN_wrapper type
#include <sst/catalog/sst_w32_SOCKADDR_IN_wrapper.h>
typedef struct sst_w32_SOCKADDR_IN_wrapper {
sst_w32_ADDRESS_FAMILY sin_family;
sst_w32_USHORT sin_port;
sst_w32_ULONG sin_addr;
} sst_w32_SOCKADDR_IN_wrapper;
The sst_w32_SOCKADDR_IN_wrapper type wraps the
sockaddr_in type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
The sst_w32_SOCKADDR_IN_wrap and sst_w32_SOCKADDR_IN_unwrap functions can be used to
convert back and forth between the sockaddr_in and
sst_w32_SOCKADDR_IN_wrapper types.
The types do not necessarily have the same ABI, so they cannot be
type punned.
3.25.67. The sst_w32_SOCKADDR_IN6 type
#include <sst/catalog/sst_w32_SOCKADDR_IN6.h>
#if SST_WITH_WINDOWS_WS2_32
typedef sockaddr_in6 sst_w32_SOCKADDR_IN6;
#endif
The sst_w32_SOCKADDR_IN6 type is equivalent to the
sockaddr_in6 type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.68. The sst_w32_SOCKADDR_IN6_unwrap function
#include <sst/catalog/sst_w32_SOCKADDR_IN6_unwrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_SOCKADDR_IN6_unwrap(
sst_w32_SOCKADDR_IN6_wrapper const * src,
sst_w32_SOCKADDR_IN6 * dst
);
#endif
The sst_w32_SOCKADDR_IN6_unwrap function converts an sst_w32_SOCKADDR_IN6_wrapper to an
sst_w32_SOCKADDR_IN6.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.69. The sst_w32_SOCKADDR_IN6_wrap function
#include <sst/catalog/sst_w32_SOCKADDR_IN6_wrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_SOCKADDR_IN6_wrap(
sst_w32_SOCKADDR_IN6 const * src,
sst_w32_SOCKADDR_IN6_wrapper * dst
);
#endif
The sst_w32_SOCKADDR_IN6_wrap function converts an sst_w32_SOCKADDR_IN6 to an
sst_w32_SOCKADDR_IN6_wrapper.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.70. The sst_w32_SOCKADDR_IN6_wrapper type
#include <sst/catalog/sst_w32_SOCKADDR_IN6_wrapper.h>
typedef struct sst_w32_SOCKADDR_IN6_wrapper {
sst_w32_ADDRESS_FAMILY sin6_family;
sst_w32_USHORT sin6_port;
sst_w32_ULONG sin6_flowinfo;
unsigned char sin6_addr[16];
sst_w32_ULONG sin6_scope_id;
} sst_w32_SOCKADDR_IN6_wrapper;
The sst_w32_SOCKADDR_IN6_wrapper type wraps the
sockaddr_in6 type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
The sst_w32_SOCKADDR_IN6_wrap and sst_w32_SOCKADDR_IN6_unwrap functions can be used to
convert back and forth between the sockaddr_in6 and
sst_w32_SOCKADDR_IN6_wrapper types.
The types do not necessarily have the same ABI, so they cannot be
type punned.
3.25.71. The sst_w32_SOCKADDR_STORAGE type
#include <sst/catalog/sst_w32_SOCKADDR_STORAGE.h>
#if SST_WITH_WINDOWS_WS2_32
typedef SOCKADDR_STORAGE sst_w32_SOCKADDR_STORAGE;
#endif
The sst_w32_SOCKADDR_STORAGE type is equivalent to the
SOCKADDR_STORAGE type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.72. The sst_w32_SOCKET type
#include <sst/catalog/sst_w32_SOCKET.h>
#if SST_WITH_WINDOWS_WS2_32
typedef SOCKET sst_w32_SOCKET;
#endif
The sst_w32_SOCKET type is equivalent to the
SOCKET type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.73. The sst_w32_socket_f function
#include <sst/catalog/sst_w32_socket_f.h>
#if SST_WITH_WINDOWS_WS2_32
sst_w32_SOCKET sst_w32_socket_f(
int af,
int type,
int protocol
);
#endif
The sst_w32_socket_f function is equivalent to the
socket function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.74. The SST_W32_SOL_SOCKET constant
#include <sst/catalog/SST_W32_SOL_SOCKET.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SOL_SOCKET (SOL_SOCKET)
#endif
The SST_W32_SOL_SOCKET constant is equivalent to the
SOL_SOCKET constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.75. The SST_W32_SOMAXCONN constant
#include <sst/catalog/SST_W32_SOMAXCONN.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_SOMAXCONN (SOMAXCONN)
#endif
The SST_W32_SOMAXCONN constant is equivalent to the
SOMAXCONN constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.76. The SST_W32_TCP_NODELAY constant
#include <sst/catalog/SST_W32_TCP_NODELAY.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_TCP_NODELAY (TCP_NODELAY)
#endif
The SST_W32_TCP_NODELAY constant is equivalent to the
TCP_NODELAY constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.77. The sst_w32_u_long type
#include <sst/catalog/sst_w32_u_long.h>
#if SST_WITH_WINDOWS_WS2_32
typedef u_long sst_w32_u_long;
#endif
The sst_w32_u_long type is equivalent to the
u_long type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.78. The sst_w32_u_short type
#include <sst/catalog/sst_w32_u_short.h>
#if SST_WITH_WINDOWS_WS2_32
typedef u_short sst_w32_u_short;
#endif
The sst_w32_u_short type is equivalent to the
u_short type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.79. The sst_w32_UINT_PTR type
#include <sst/catalog/sst_w32_UINT_PTR.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef UINT_PTR sst_w32_UINT_PTR;
#endif
The sst_w32_UINT_PTR type is equivalent to the
UINT_PTR type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.80. The sst_w32_ULONG type
#include <sst/catalog/sst_w32_ULONG.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef ULONG sst_w32_ULONG;
#endif
The sst_w32_ULONG type is equivalent to the
ULONG type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.81. The sst_w32_USHORT type
#include <sst/catalog/sst_w32_USHORT.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef USHORT sst_w32_USHORT;
#endif
The sst_w32_USHORT type is equivalent to the
USHORT type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.82. The sst_w32_VOID type
#include <sst/catalog/sst_w32_VOID.h>
#if SST_WITH_WINDOWS_KERNEL32
typedef VOID sst_w32_VOID;
#endif
The sst_w32_VOID type is equivalent to the
VOID type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.83. The sst_w32_WORD type
#include <sst/catalog/sst_w32_WORD.h>
typedef WORD sst_w32_WORD;
The sst_w32_WORD type is equivalent to the
WORD type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.84. The sst_w32_WSACleanup function
#include <sst/catalog/sst_w32_WSACleanup.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_WSACleanup(
);
#endif
The sst_w32_WSACleanup function is equivalent to the
WSACleanup function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.85. The sst_w32_WSADATA type
#include <sst/catalog/sst_w32_WSADATA.h>
#if SST_WITH_WINDOWS_WS2_32
typedef WSADATA sst_w32_WSADATA;
#endif
The sst_w32_WSADATA type is equivalent to the
WSADATA type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.86. The sst_w32_WSADATA_unwrap function
#include <sst/catalog/sst_w32_WSADATA_unwrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_WSADATA_unwrap(
sst_w32_WSADATA_wrapper const * src,
sst_w32_WSADATA * dst
);
#endif
The sst_w32_WSADATA_unwrap function converts an sst_w32_WSADATA_wrapper to an
sst_w32_WSADATA.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.87. The sst_w32_WSADATA_wrap function
#include <sst/catalog/sst_w32_WSADATA_wrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_WSADATA_wrap(
sst_w32_WSADATA const * src,
sst_w32_WSADATA_wrapper * dst
);
#endif
The sst_w32_WSADATA_wrap function converts an sst_w32_WSADATA to an
sst_w32_WSADATA_wrapper.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.88. The sst_w32_WSADATA_wrapper type
#include <sst/catalog/sst_w32_WSADATA_wrapper.h>
typedef struct sst_w32_WSADATA_wrapper {
sst_w32_WORD wVersion;
sst_w32_WORD wHighVersion;
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char * lpVendorInfo;
char szDescription[SST_W32_WSADESCRIPTION_LEN + 1];
char szSystemStatus[SST_W32_WSASYS_STATUS_LEN + 1];
} sst_w32_WSADATA_wrapper;
The sst_w32_WSADATA_wrapper type wraps the
WSADATA type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
The sst_w32_WSADATA_wrap and sst_w32_WSADATA_unwrap functions can be used to
convert back and forth between the WSADATA and
sst_w32_WSADATA_wrapper types.
The types do not necessarily have the same ABI, so they cannot be
type punned.
3.25.89. The SST_W32_WSADESCRIPTION_LEN constant
#include <sst/catalog/SST_W32_WSADESCRIPTION_LEN.h>
#define SST_W32_WSADESCRIPTION_LEN (WSADESCRIPTION_LEN)
The SST_W32_WSADESCRIPTION_LEN constant is equivalent to the
WSADESCRIPTION_LEN constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.90. The SST_W32_WSAEALREADY constant
#include <sst/catalog/SST_W32_WSAEALREADY.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_WSAEALREADY (WSAEALREADY)
#endif
The SST_W32_WSAEALREADY constant is equivalent to the
WSAEALREADY constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.91. The SST_W32_WSAEISCONN constant
#include <sst/catalog/SST_W32_WSAEISCONN.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_WSAEISCONN (WSAEISCONN)
#endif
The SST_W32_WSAEISCONN constant is equivalent to the
WSAEISCONN constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.92. The SST_W32_WSAEWOULDBLOCK constant
#include <sst/catalog/SST_W32_WSAEWOULDBLOCK.h>
#if SST_WITH_WINDOWS_WS2_32
#define SST_W32_WSAEWOULDBLOCK (WSAEWOULDBLOCK)
#endif
The SST_W32_WSAEWOULDBLOCK constant is equivalent to the
WSAEWOULDBLOCK constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.93. The sst_w32_WSAGetLastError function
#include <sst/catalog/sst_w32_WSAGetLastError.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_WSAGetLastError(
);
#endif
The sst_w32_WSAGetLastError function is equivalent to the
WSAGetLastError function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.94. The sst_w32_WSAPoll function
#include <sst/catalog/sst_w32_WSAPoll.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_WSAPoll(
sst_w32_WSAPOLLFD * fdArray,
sst_w32_ULONG fds,
sst_w32_INT timeout
);
#endif
The sst_w32_WSAPoll function is equivalent to the
WSAPoll function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.95. The sst_w32_WSAPOLLFD type
#include <sst/catalog/sst_w32_WSAPOLLFD.h>
#if SST_WITH_WINDOWS_WS2_32
typedef WSAPOLLFD sst_w32_WSAPOLLFD;
#endif
The sst_w32_WSAPOLLFD type is equivalent to the
WSAPOLLFD type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.96. The sst_w32_WSAPOLLFD_unwrap function
#include <sst/catalog/sst_w32_WSAPOLLFD_unwrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_WSAPOLLFD_unwrap(
sst_w32_WSAPOLLFD_wrapper const * src,
sst_w32_WSAPOLLFD * dst
);
#endif
The sst_w32_WSAPOLLFD_unwrap function converts an sst_w32_WSAPOLLFD_wrapper to an
sst_w32_WSAPOLLFD.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.97. The sst_w32_WSAPOLLFD_wrap function
#include <sst/catalog/sst_w32_WSAPOLLFD_wrap.h>
#if SST_WITH_WINDOWS_WS2_32
void sst_w32_WSAPOLLFD_wrap(
sst_w32_WSAPOLLFD const * src,
sst_w32_WSAPOLLFD_wrapper * dst
);
#endif
The sst_w32_WSAPOLLFD_wrap function converts an sst_w32_WSAPOLLFD to an
sst_w32_WSAPOLLFD_wrapper.
All data in src that corresponds to data in dst must be fully
initialized.
In particular, array members must be fully initialized, even if they
store sparse data such as null-terminated strings.
3.25.98. The sst_w32_WSAPOLLFD_wrapper type
#include <sst/catalog/sst_w32_WSAPOLLFD_wrapper.h>
typedef struct pollfd {
sst_w32_SOCKET fd;
sst_w32_SHORT events;
sst_w32_SHORT revents;
} sst_w32_WSAPOLLFD_wrapper;
The sst_w32_WSAPOLLFD_wrapper type wraps the
WSAPOLLFD type from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
The sst_w32_WSAPOLLFD_wrap and sst_w32_WSAPOLLFD_unwrap functions can be used to
convert back and forth between the WSAPOLLFD and
sst_w32_WSAPOLLFD_wrapper types.
The types do not necessarily have the same ABI, so they cannot be
type punned.
3.25.99. The sst_w32_WSAStartup function
#include <sst/catalog/sst_w32_WSAStartup.h>
#if SST_WITH_WINDOWS_WS2_32
int sst_w32_WSAStartup(
sst_w32_WORD wVersionRequested,
sst_w32_WSADATA * lpWSAData
);
#endif
The sst_w32_WSAStartup function is equivalent to the
WSAStartup function from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.100. The SST_W32_WSASYS_STATUS_LEN constant
#include <sst/catalog/SST_W32_WSASYS_STATUS_LEN.h>
#define SST_W32_WSASYS_STATUS_LEN (WSASYS_STATUS_LEN)
The SST_W32_WSASYS_STATUS_LEN constant is equivalent to the
WSASYS_STATUS_LEN constant from the Windows
API.
It does not require any Windows API headers to be included, which helps
reduce compilation difficulties.
3.25.101. The sst::windows_langid enumeration
#include <sst/catalog/windows_langid.hpp>
namespace sst {
enum class windows_langid : T {
en_us = 0x0409,
};
}
The sst::windows_langid enumeration provides Windows language ID
constants.
The underlying type T is an unspecified unsigned
fundamental integer type[3] with at least 16-bit range.
3.25.102. The sst::wsa_error_string function
#include <sst/catalog/wsa_error_string.hpp>
namespace sst {
#if SST_WITH_WINDOWS_WS2_32
std::string wsa_error_string(int code);
#endif
}
The sst::wsa_error_string function returns a string representing
the Windows Sockets error code code.
3.25.103. The sst::windows_socket_library_scope class
#include <sst/catalog/windows_socket_library_scope.hpp>
namespace sst {
class windows_socket_library_scope final {
public:
explicit windows_socket_library_scope(int major, int minor);
explicit windows_socket_library_scope();
sst_w32_WSADATA_wrapper const & data() const;
~windows_socket_library_scope() noexcept;
windows_socket_library_scope(windows_socket_library_scope const &) = delete;
windows_socket_library_scope(windows_socket_library_scope &&) = delete;
windows_socket_library_scope & operator=(windows_socket_library_scope const &) = delete;
windows_socket_library_scope & operator=(windows_socket_library_scope &&) = delete;
};
}
The sst::windows_socket_library_scope class calls the WSAStartup
function when it is constructed and the WSACleanup function
when it is destructed.
If Winsock is not available, i.e., if SST_WITH_WINDOWS_WS2_32 is
0, this class does nothing.
3.25.103.1. The sst::windows_socket_library_scope (overload 1) constructor
explicit windows_socket_library_scope(int major, int minor);
The sst::windows_socket_library_scope (overload 1) constructor calls the
WSAStartup function and requests the Winsock version
specified by major and minor.
If Winsock is not available, i.e., if SST_WITH_WINDOWS_WS2_32 is
0, this constructor does nothing.
3.25.103.2. The sst::windows_socket_library_scope (overload 2) constructor
explicit windows_socket_library_scope();
The sst::windows_socket_library_scope (overload 2) constructor calls the
WSAStartup function and requests Winsock version 2.2.
If Winsock is not available, i.e., if SST_WITH_WINDOWS_WS2_32 is
0, this constructor does nothing.
3.25.103.3. The sst::windows_socket_library_scope::data function
sst_w32_WSADATA_wrapper const & data() const;
The sst::windows_socket_library_scope::data function returns a reference to
the sst_w32_WSADATA_wrapper object that resulted from the
WSAStartup call made by the constructor.
If Winsock is not available, i.e., if SST_WITH_WINDOWS_WS2_32 is
0, all data in the sst_w32_WSADATA_wrapper object will be zero.
3.25.103.4. The sst::~windows_socket_library_scope destructor
~windows_socket_library_scope() noexcept;
The sst::~windows_socket_library_scope destructor calls the
WSACleanup function.
If Winsock is not available, i.e., if SST_WITH_WINDOWS_WS2_32 is
0, this destructor does nothing.
3.26. Miscellaneous
3.26.1. The sst::value_bits trait
#include <sst/catalog/value_bits.hpp>
// or: <sst/limits.h>
namespace sst {
template<class T>
class value_bits
: public std::integral_constant<sst::remove_cvref_t<T>, /*...*/> {};
}
The sst::value_bits class provides the number of value bits[7] in
the integer type T.
|
Important
|
Since |
sst-example-49.cpp#include <iomanip>
#include <ios>
#include <iostream>
#include <sst/limits.h>
#include <sst/catalog/to_string.hpp>
#include <string>
namespace {
template<class T>
void info(std::string const & T_name) {
T const v = sst::value_bits<T>::value;
std::cout << "sst::value_bits<";
std::cout << std::left << std::setw(18) << T_name;
std::cout << ">::value == ";
std::cout << std::right << std::setw(2) << sst::to_string(v);
std::cout << "\n";
}
#define INFO(T) info<T>(#T)
} // namespace
int main() {
INFO(bool);
INFO(char);
INFO(signed char);
INFO(unsigned char);
INFO(short);
INFO(unsigned short);
INFO(int);
INFO(unsigned int);
INFO(long);
INFO(unsigned long);
INFO(long long);
INFO(unsigned long long);
}
g++ sst-example-49.cpp -lsst
sst::value_bits<bool >::value == 1 sst::value_bits<char >::value == 7 sst::value_bits<signed char >::value == 7 sst::value_bits<unsigned char >::value == 8 sst::value_bits<short >::value == 15 sst::value_bits<unsigned short >::value == 16 sst::value_bits<int >::value == 31 sst::value_bits<unsigned int >::value == 32 sst::value_bits<long >::value == 63 sst::value_bits<unsigned long >::value == 64 sst::value_bits<long long >::value == 63 sst::value_bits<unsigned long long>::value == 64
3.26.2. The sst::width_bits trait
#include <sst/catalog/width_bits.hpp>
// or: <sst/limits.h>
namespace sst {
template<class T>
class width_bits
: public std::integral_constant<sst::remove_cvref_t<T>, /*...*/> {};
}
The sst::width_bits class provides the number of width bits[6] in
the integer type T.
|
Important
|
Since |
sst-example-50.cpp#include <iomanip>
#include <ios>
#include <iostream>
#include <sst/limits.h>
#include <sst/catalog/to_string.hpp>
#include <string>
namespace {
template<class T>
void info(std::string const & T_name) {
T const v = sst::width_bits<T>::value;
std::cout << "sst::width_bits<";
std::cout << std::left << std::setw(18) << T_name;
std::cout << ">::value == ";
std::cout << std::right << std::setw(2) << sst::to_string(v);
std::cout << "\n";
}
#define INFO(T) info<T>(#T)
} // namespace
int main() {
INFO(bool);
INFO(char);
INFO(signed char);
INFO(unsigned char);
INFO(short);
INFO(unsigned short);
INFO(int);
INFO(unsigned int);
INFO(long);
INFO(unsigned long);
INFO(long long);
INFO(unsigned long long);
}
g++ sst-example-50.cpp -lsst
sst::width_bits<bool >::value == 1 sst::width_bits<char >::value == 8 sst::width_bits<signed char >::value == 8 sst::width_bits<unsigned char >::value == 8 sst::width_bits<short >::value == 16 sst::width_bits<unsigned short >::value == 16 sst::width_bits<int >::value == 32 sst::width_bits<unsigned int >::value == 32 sst::width_bits<long >::value == 64 sst::width_bits<unsigned long >::value == 64 sst::width_bits<long long >::value == 64 sst::width_bits<unsigned long long>::value == 64
3.26.3. The sst::type_min trait
#include <sst/catalog/type_min.hpp>
// or: <sst/limits.h>
namespace sst {
// (1)
template<std::integral T>
struct type_min : std::integral_constant<T, v> {};
}
The sst::type_min trait provides the minimum value of a type.
-
Provides the minimum value of a fundamental integer type[3].
|
Important
|
Since |
3.26.4. The sst::type_max trait
#include <sst/catalog/type_max.hpp>
// or: <sst/limits.h>
namespace sst {
// (1)
template<std::integral T>
struct type_max : std::integral_constant<T, v> {};
}
The sst::type_max trait provides the maximum value of a type.
-
Provides the maximum value of a fundamental integer type[3].
|
Important
|
Since |
3.26.5. The sst::type_msb trait
#include <sst/catalog/type_msb.hpp>
// or: <sst/bit.h>
namespace sst {
template<class IntType>
struct type_msb
: std::integral_constant<IntType, /*...*/> {};
}
The sst::type_msb trait provides the value of integer type
IntType whose value bits[7] are all set to 0 except for the most
significant value bit, which is set to 1.
|
Important
|
Since |
3.26.6. The sst::char_bit trait
#include <sst/limits.h>
namespace sst {
using char_bit = sst::width_bits<unsigned char>;
}
The sst::char_bit class provides the value of CHAR_BIT.
3.26.7. The sst::uchar_max type alias
#include <sst/catalog/uchar_max.hpp>
// or: <sst/limits.h>
namespace sst {
using uchar_max = sst::type_max<unsigned char>;
}
The sst::uchar_max type alias provides an
alternative name for sst::type_max<unsigned char>.
3.26.8. The sst::promote trait
#include <sst/catalog/promote.hpp>
// or: <sst/type.h>
namespace sst {
// (1)
template<std::integral T>
struct promote { using type = R; };
}
3.26.9. The sst::promotes trait
#include <sst/catalog/promotes.hpp>
// or: <sst/type.h>
namespace sst {
template<class T>
struct promotes : std::integral_constant<bool, b>;
}
The sst::promotes trait determines whether a type promotes to a type
different from itself.
|
Important
|
Since |
3.26.10. The sst::checked_t class
#include <sst/checked.h>
namespace sst {
template<class T>
class checked_t {
// Underlying value retrieval
constexpr T value() const noexcept;
};
}
The sst::checked_t class provides range-checked integer arithmetic.
Any value x of any integer type can be converted to an
sst::checked_t<T> value via the converting constructor
sst::checked_t<T>(x), where T is also any integer type.
If x cannot be represented by T, the constructor will throw an
exception.
Arbitrary integer arithmetic can then be performed on the
sst::checked_t<T> value, which will cause the arithmetic to be
range-checked_t: an exception will be thrown if there is
any attempt to hold a value in a type that cannot represent the value,
and every result that would have had type R will instead have type
sst::checked_t<R>.
After the arithmetic is complete, the underlying value can be retrieved
with the value() function.
Unlike in normal integer arithmetic, unsigned integer types are not considered to be modular. If a value cannot be represented by an unsigned integer type, an exception will be thrown instead of reducing it modularly in that type.
[cl_sst_checked](INT_MIN) - 1; // throws
[cl_sst_checked](0U) - 1U; // throws
3.26.11. The sst::checked function
#include <sst/checked.h>
namespace sst {
template<class T>
checked_t<T> checked(T x) noexcept;
}
The sst::checked function converts a value of integer type
T to an [cl_sst_checked_t]<T>.
3.26.12. The sst::checked_cast function
#include <sst/checked.h>
namespace sst {
template<class T, class U>
[cl_SST_CPP14_CONSTEXPR] T checked_cast(U x);
}
The sst::checked_cast function converts a value of integer type
U to a value of integer type T, throwing an
exception if the value cannot be represented
by T.
3.26.13. The sst::perfect_lt function
#include <sst/catalog/perfect_lt.hpp>
// or: <sst/integer.h>
namespace sst {
template<std::integral T1, std::integral T2>
constexpr bool perfect_lt(T1 x, T2 y) noexcept;
}
The sst::perfect_lt function determines whether x is less than y for any two
values x and y of any two integer types T1 and T2.
The usual arithmetic conversions can cause the plain <
operator to yield an unexpected result when T1 and T2 have different
signedness and the signed value is negative.
Using the sst::perfect_lt function instead of the plain < operator will
avoid this possibility.
The sst::perfect_lt function may have a small amount of overhead compared to
the plain < operator, so it should be used judiciously.
3.26.14. The sst::perfect_gt function
#include <sst/catalog/perfect_gt.hpp>
// or: <sst/integer.h>
namespace sst {
template<std::integral T1, std::integral T2>
constexpr bool perfect_gt(T1 x, T2 y) noexcept;
}
The sst::perfect_gt function determines whether x is greater than y for any two
values x and y of any two integer types T1 and T2.
The usual arithmetic conversions can cause the plain >
operator to yield an unexpected result when T1 and T2 have different
signedness and the signed value is negative.
Using the sst::perfect_gt function instead of the plain > operator will
avoid this possibility.
The sst::perfect_gt function may have a small amount of overhead compared to
the plain > operator, so it should be used judiciously.
3.26.15. The sst::perfect_le function
#include <sst/catalog/perfect_le.hpp>
// or: <sst/integer.h>
namespace sst {
template<std::integral T1, std::integral T2>
constexpr bool perfect_le(T1 x, T2 y) noexcept;
}
The sst::perfect_le function determines whether x is less than or equal to y for any two
values x and y of any two integer types T1 and T2.
The usual arithmetic conversions can cause the plain <=
operator to yield an unexpected result when T1 and T2 have different
signedness and the signed value is negative.
Using the sst::perfect_le function instead of the plain <= operator will
avoid this possibility.
The sst::perfect_le function may have a small amount of overhead compared to
the plain ⇐ operator, so it should be used judiciously.
3.26.16. The sst::perfect_ge function
#include <sst/catalog/perfect_ge.hpp>
// or: <sst/integer.h>
namespace sst {
template<std::integral T1, std::integral T2>
constexpr bool perfect_ge(T1 x, T2 y) noexcept;
}
The sst::perfect_ge function determines whether x is greater than or equal to y for any two
values x and y of any two integer types T1 and T2.
The usual arithmetic conversions can cause the plain >=
operator to yield an unexpected result when T1 and T2 have different
signedness and the signed value is negative.
Using the sst::perfect_ge function instead of the plain >= operator will
avoid this possibility.
The sst::perfect_ge function may have a small amount of overhead compared to
the plain >= operator, so it should be used judiciously.
3.26.17. The sst::perfect_eq function
#include <sst/catalog/perfect_eq.hpp>
// or: <sst/integer.h>
namespace sst {
template<std::integral T1, std::integral T2>
constexpr bool perfect_eq(T1 x, T2 y) noexcept;
}
The sst::perfect_eq function determines whether x is equal to y for any two
values x and y of any two integer types T1 and T2.
The usual arithmetic conversions can cause the plain ==
operator to yield an unexpected result when T1 and T2 have different
signedness and the signed value is negative.
Using the sst::perfect_eq function instead of the plain == operator will
avoid this possibility.
The sst::perfect_eq function may have a small amount of overhead compared to
the plain == operator, so it should be used judiciously.
3.26.18. The sst::perfect_ne function
#include <sst/catalog/perfect_ne.hpp>
// or: <sst/integer.h>
namespace sst {
template<std::integral T1, std::integral T2>
constexpr bool perfect_ne(T1 x, T2 y) noexcept;
}
The sst::perfect_ne function determines whether x is unequal to y for any two
values x and y of any two integer types T1 and T2.
The usual arithmetic conversions can cause the plain !=
operator to yield an unexpected result when T1 and T2 have different
signedness and the signed value is negative.
Using the sst::perfect_ne function instead of the plain != operator will
avoid this possibility.
The sst::perfect_ne function may have a small amount of overhead compared to
the plain != operator, so it should be used judiciously.
3.26.19. The sst::unsigned_lt function
#include <sst/catalog/unsigned_lt.hpp>
// or: <sst/integer.h>
namespace sst {
template<class IntType1, class IntType2>
constexpr bool unsigned_lt(IntType1 a, IntType2 b) noexcept;
}
The sst::unsigned_lt function determines whether a is less than b for any two
nonnegative values a and b of any two integer types IntType1
and IntType2 without generating any compiler warnings.
The usual arithmetic conversions guarantee that comparing a
to b with the plain < operator always yields the expected result
if a and b are nonnegative, but it is common for compilers to
generate warnings when IntType1 and IntType2 have different
signedness.
This can be annoying when writing template functions for arbitrary
integer types, as certain type combinations can generate useless
warnings.
Using the sst::unsigned_lt function instead of the plain < operator will
avoid these warnings.
The sst::unsigned_lt function does not have any overhead compared to the plain
< operator.
If a is negative or b is negative, the behavior is undefined.
3.26.20. The sst::unsigned_gt function
#include <sst/catalog/unsigned_gt.hpp>
// or: <sst/integer.h>
namespace sst {
template<class IntType1, class IntType2>
constexpr bool unsigned_gt(IntType1 a, IntType2 b) noexcept;
}
The sst::unsigned_gt function determines whether a is greater than b for any two
nonnegative values a and b of any two integer types IntType1
and IntType2 without generating any compiler warnings.
The usual arithmetic conversions guarantee that comparing a
to b with the plain > operator always yields the expected result
if a and b are nonnegative, but it is common for compilers to
generate warnings when IntType1 and IntType2 have different
signedness.
This can be annoying when writing template functions for arbitrary
integer types, as certain type combinations can generate useless
warnings.
Using the sst::unsigned_gt function instead of the plain > operator will
avoid these warnings.
The sst::unsigned_gt function does not have any overhead compared to the plain
> operator.
If a is negative or b is negative, the behavior is undefined.
3.26.21. The sst::unsigned_le function
#include <sst/catalog/unsigned_le.hpp>
// or: <sst/integer.h>
namespace sst {
template<class IntType1, class IntType2>
constexpr bool unsigned_le(IntType1 a, IntType2 b) noexcept;
}
The sst::unsigned_le function determines whether a is less than or equal to b for any two
nonnegative values a and b of any two integer types IntType1
and IntType2 without generating any compiler warnings.
The usual arithmetic conversions guarantee that comparing a
to b with the plain <= operator always yields the expected result
if a and b are nonnegative, but it is common for compilers to
generate warnings when IntType1 and IntType2 have different
signedness.
This can be annoying when writing template functions for arbitrary
integer types, as certain type combinations can generate useless
warnings.
Using the sst::unsigned_le function instead of the plain <= operator will
avoid these warnings.
The sst::unsigned_le function does not have any overhead compared to the plain
⇐ operator.
If a is negative or b is negative, the behavior is undefined.
3.26.22. The sst::unsigned_ge function
#include <sst/catalog/unsigned_ge.hpp>
// or: <sst/integer.h>
namespace sst {
template<class IntType1, class IntType2>
constexpr bool unsigned_ge(IntType1 a, IntType2 b) noexcept;
}
The sst::unsigned_ge function determines whether a is greater than or equal to b for any two
nonnegative values a and b of any two integer types IntType1
and IntType2 without generating any compiler warnings.
The usual arithmetic conversions guarantee that comparing a
to b with the plain >= operator always yields the expected result
if a and b are nonnegative, but it is common for compilers to
generate warnings when IntType1 and IntType2 have different
signedness.
This can be annoying when writing template functions for arbitrary
integer types, as certain type combinations can generate useless
warnings.
Using the sst::unsigned_ge function instead of the plain >= operator will
avoid these warnings.
The sst::unsigned_ge function does not have any overhead compared to the plain
>= operator.
If a is negative or b is negative, the behavior is undefined.
3.26.23. The sst::unsigned_eq function
#include <sst/catalog/unsigned_eq.hpp>
// or: <sst/integer.h>
namespace sst {
template<class IntType1, class IntType2>
constexpr bool unsigned_eq(IntType1 a, IntType2 b) noexcept;
}
The sst::unsigned_eq function determines whether a is equal to b for any two
nonnegative values a and b of any two integer types IntType1
and IntType2 without generating any compiler warnings.
The usual arithmetic conversions guarantee that comparing a
to b with the plain == operator always yields the expected result
if a and b are nonnegative, but it is common for compilers to
generate warnings when IntType1 and IntType2 have different
signedness.
This can be annoying when writing template functions for arbitrary
integer types, as certain type combinations can generate useless
warnings.
Using the sst::unsigned_eq function instead of the plain == operator will
avoid these warnings.
The sst::unsigned_eq function does not have any overhead compared to the plain
== operator.
If a is negative or b is negative, the behavior is undefined.
3.26.24. The sst::unsigned_ne function
#include <sst/catalog/unsigned_ne.hpp>
// or: <sst/integer.h>
namespace sst {
template<class IntType1, class IntType2>
constexpr bool unsigned_ne(IntType1 a, IntType2 b) noexcept;
}
The sst::unsigned_ne function determines whether a is unequal to b for any two
nonnegative values a and b of any two integer types IntType1
and IntType2 without generating any compiler warnings.
The usual arithmetic conversions guarantee that comparing a
to b with the plain != operator always yields the expected result
if a and b are nonnegative, but it is common for compilers to
generate warnings when IntType1 and IntType2 have different
signedness.
This can be annoying when writing template functions for arbitrary
integer types, as certain type combinations can generate useless
warnings.
Using the sst::unsigned_ne function instead of the plain != operator will
avoid these warnings.
The sst::unsigned_ne function does not have any overhead compared to the plain
!= operator.
If a is negative or b is negative, the behavior is undefined.
3.26.25. sst::strict_eq
#include <sst/catalog/strict_eq.hpp>
sst::strict_eq(x, y)
The sst::strict_eq function returns true if all of the
following conditions are satisfied, or false if not:
-
xandyhave the same type ignoring any cvref-qualifiers. -
x == yistrue.
If the first condition is not satisfied, then the second condition will
not be subject to compilation.
In other words, if x and y have different types, then the function
will return false even if x == y would not compile.
If the first condition is not satisfied, then the function will be
SST_CONSTEVAL.
Otherwise, the function will be constexpr.
3.26.26. The sst::ones_mask function
#include <sst/catalog/ones_mask.hpp>
// or: <sst/bit.h>
namespace sst {
// (1)
template<class IntType1, class IntType2>
constexpr IntType1 ones_mask(IntType2 n) noexcept;
// (2)
template<class IntType1, class IntType2, class IntType3>
constexpr IntType1 ones_mask(IntType2 n, IntType3 k) noexcept;
}
The sst::ones_mask function returns
\((2^\mathtt{n} - 1) \cdot 2^\mathtt{k}\), where k is taken to be
zero if it is omitted.
This is the bit mask consisting of n one bits followed by k zero
bits.
If n is negative or k is negative, the behavior is undefined.
For (1) and (2), if \(\mathtt{n} + \mathtt{k}\) is greater than the
number of value bits[7] in IntType1, the behavior is undefined.
3.26.27. The sst::uchar_msb trait
#include <sst/catalog/uchar_msb.hpp>
// or: <sst/bit.h>
namespace sst {
using uchar_msb = [cl_sst_type_msb]<unsigned char>;
SST_CPP17_INLINE constexpr unsigned char uchar_msb_v = sst::uchar_msb::value;
}
The sst::uchar_msb trait provides the value of type unsigned char whose
value bits[7] are all set to 0 except for the most significant value
bit, which is set to 1.
3.26.28. The sst::boxed class template
The sst::boxed class template describes a class that stores a value of
type T as a distinct type identified by type Tag in addition to type
T, allowing different kinds of values of type T to be distinguished
from each other.
#include <sst/catalog/boxed.hpp>
namespace sst {
template<class T, class Tag>
class boxed {
public:
using value_type = T;
// Construction is forwarded to T.
template<class... Args> explicit constexpr boxed(Args &&... args);
// Copy construction, copy assignment, move construction, move
// assignment, and destruction are intentionally implicit.
// Value retrieval
explicit SST_CPP14_CONSTEXPR operator T &() noexcept;
explicit constexpr operator T const &() const noexcept;
SST_CPP14_CONSTEXPR T & value() noexcept;
constexpr T const & value() const noexcept;
// Comparisons for aliases and publicly derived classes
constexpr bool operator<(boxed const & b) const
noexcept(noexcept(std::declval<T>() < std::declval<T>()));
constexpr bool operator>(boxed const & b) const
noexcept(noexcept(std::declval<T>() > std::declval<T>()));
constexpr bool operator<=(boxed const & b) const
noexcept(noexcept(std::declval<T>() <= std::declval<T>()));
constexpr bool operator>=(boxed const & b) const
noexcept(noexcept(std::declval<T>() >= std::declval<T>()));
constexpr bool operator==(boxed const & b) const
noexcept(noexcept(std::declval<T>() == std::declval<T>()));
constexpr bool operator!=(boxed const & b) const
noexcept(noexcept(std::declval<T>() != std::declval<T>()));
// Comparisons for privately derived classes
constexpr bool operator<(Tag const & b) const
noexcept(noexcept(std::declval<T>() < std::declval<T>()));
constexpr bool operator>(Tag const & b) const
noexcept(noexcept(std::declval<T>() > std::declval<T>()));
constexpr bool operator<=(Tag const & b) const
noexcept(noexcept(std::declval<T>() <= std::declval<T>()));
constexpr bool operator>=(Tag const & b) const
noexcept(noexcept(std::declval<T>() >= std::declval<T>()));
constexpr bool operator==(Tag const & b) const
noexcept(noexcept(std::declval<T>() == std::declval<T>()));
constexpr bool operator!=(Tag const & b) const
noexcept(noexcept(std::declval<T>() != std::declval<T>()));
};
}
3.26.29. The sst::bignum class
#include <sst/catalog/bignum.hpp>
namespace sst {
class bignum {
template<std::integral T>
explicit operator T() const;
};
}
3.26.29.1. Conversion to fundamental integer types
template<std::integral T>
explicit operator T() const;
This operator converts the value of the big integer to a
fundamental integer type[3] T.
If T is unsigned, the conversion is modular.
3.26.30. The sst::elgamal::cipher class
#include <sst/catalog/elgamal.hpp>
#include <sst/catalog/bignum.hpp>
#include <openssl/ec.h>
namespace sst {
namespace elgamal {
class cipher {
cipher(EC_GROUP const * const group,
sst::bignum const & skey,
EC_POINT const * const pkey);
cipher(EC_GROUP const * const group,
EC_POINT const * const pkey);
cipher(EC_GROUP const * const group);
cipher(int const curve_nid);
sst::elgamal::ciphertext
encrypt_small_domain(std::vector<unsigned char> const & message) const;
sst::elgamal::ciphertext
encrypt_small_domain(std::size_t const & message) const;
unsigned char
decrypt_small_domain(sst::elgamal::ciphertext const & message_enc) const;
std::vector<unsigned char> serialize_secret_key() const;
std::vector<unsigned char> serialize_public_key() const;
void deserialize_skey(std::vector<unsigned char> const & src);
void deserialize_pkey(std::vector<unsigned char> const & src,
std::vector<unsigned char>::size_type & idx);
void keygen();
};
}
}
The class sst::elgamal::cipher is meant to store the relevant
information needed to perform Elgamal encryption, as well as some
helper methods. The underlying elliptic curve EC_GROUP will be set
at initialization, but both the EC_POINT public key and
sst::bignum secret key can be set after initialization. The method
keygen can be called to generate such a key pair.
The method encrypt_small_domain takes a message (as either a
std::size_t number m or a std::vector<unsigned char> buffer
which is encoded as a number m) and computes
\(\mathrm{message}:= g^m\), where \(g\) is the
generator of the elliptic curve group . Finally, Elgamal encryption
(using the public key \(\mathrm{pkey}\)) is performed on
\(\mathrm{message}\) to produce the corresponding ciphertext:
The method decrypt_small_domain uses the secret key
\(\mathrm{skey}\) to convert the ciphertext to an EC_POINT,
which is then decoded (one byte at a time) to recover the original
message.
There are also methods for serializing and deserializing both public and secret keys.
3.26.31. The sst::str_cmp function
#include <sst/catalog/str_cmp.hpp>
namespace sst {
template<class IteratorA,
class IteratorB,
class ValueType =
typename std::iterator_traits<IteratorA>::value_type>
constexpr int str_cmp(IteratorA a,
IteratorB b,
ValueType const & null_terminator = ValueType());
}
The sst::str_cmp function compares the two null-terminated
sequences a and b and returns a value less than, equal to, or
greater than zero if a is less than, equal to, or greater than b,
respectively.
a.cpp#include <iostream>
#include <vector>
#include <sst/catalog/str_cmp.hpp>
int main() {
std::cout << sst::str_cmp("foo", "foo") << "\n";
std::cout << sst::str_cmp("foo", "Foo") << "\n";
std::cout << sst::str_cmp(L"Foo", L"foo") << "\n";
std::vector<int> x{1, 2, 3, 4, 5, 6};
std::vector<int> y{1, 2, 3, 6, 5};
std::cout << sst::str_cmp(x.begin(), y.begin(), 3) << "\n";
std::cout << sst::str_cmp(x.begin(), y.begin(), 5) << "\n";
std::cout << sst::str_cmp(x.begin(), y.begin(), 6) << "\n";
}
$ g++ a.cpp -lsst $ ./a.out 0 1 -1 0 -1 1
3.26.32. The sst::opt_arg enumeration
#include <sst/catalog/opt_arg.hpp>
namespace sst {
enum class opt_arg {
required,
permitted,
forbidden
};
}
3.26.33. The sst::opt_exception exception
#include <sst/catalog/opt_exception.hpp>
namespace sst {
struct opt_exception : std::runtime_error {
using std::runtime_error::runtime_error;
};
}
3.26.34. The sst::parse_opt function
#include <sst/catalog/parse_opt.hpp>
namespace sst {
template<class StringList, class String>
auto parse_opt(StringList & args,
String const & opt,
opt_arg style = opt_arg::required,
bool * has_arg = nullptr) ->
typename std::enable_if<!std::is_pointer<String>::value,
bool>::type;
template<class StringList, class CharT>
bool parse_opt(StringList & args,
CharT const * opt,
opt_arg style = opt_arg::required,
bool * has_arg = nullptr);
template<class StringList, class String1, class String2>
bool parse_opt(StringList & args,
std::initializer_list<String1> opts,
String2 * parsed_opt = nullptr,
opt_arg style = opt_arg::required,
bool * has_arg = nullptr);
template<class StringList, class String>
bool parse_opt(StringList & args,
std::initializer_list<String> opts,
opt_arg style = opt_arg::required,
bool * has_arg = nullptr);
}
The following program demonstrates how sst::parse_opt could be used to
parse the command-line arguments similarly to the git init command of
Git 2.31.0 (see
https://github.com/git/git/blob/v2.31.0/Documentation/git-init.txt):
//
// Copyright (C) 2012-2024 Stealth Software Technologies, 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 (including
// the next paragraph) 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.
//
// SPDX-License-Identifier: MIT
//
#include <cstdlib>
#include <exception>
#include <iostream>
#include <list>
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/opt_arg.hpp[sst/catalog/opt_arg.hpp,window=_blank]>
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/parse_opt.hpp[sst/catalog/parse_opt.hpp,window=_blank]>
#include <link:{repo_browser_url}/src/c-cpp/include/sst/catalog/unknown_opt.hpp[sst/catalog/unknown_opt.hpp,window=_blank]>
#include <stdexcept>
#include <string>
#include <utility>
int main(int const argc, char ** const argv) {
char const * const argv0 = argc > 0 ? argv[0] : "example";
try {
std::list<std::string> args(argv, argv + argc);
if (args.empty()) {
throw std::runtime_error("argc is zero");
}
bool parse_options = true;
std::string directory = ".";
bool directory_given = false;
while (args.pop_front(), !args.empty()) {
if (parse_options) {
bool has_arg;
if (sst::parse_opt(args, "--", sst::opt_arg::forbidden)) {
parse_options = false;
continue;
}
if (sst::parse_opt(args,
{"-q", "--quiet"},
sst::opt_arg::forbidden)) {
// ...
continue;
}
if (sst::parse_opt(args, "--bare", sst::opt_arg::forbidden)) {
// ...
continue;
}
if (sst::parse_opt(args, "--object-format")) {
std::string & arg = args.front();
// ...
continue;
}
if (sst::parse_opt(args, "--template")) {
std::string & arg = args.front();
// ...
continue;
}
if (sst::parse_opt(args, "--separate-git-dir")) {
std::string & arg = args.front();
// ...
continue;
}
if (sst::parse_opt(args, {"-b", "--initial-branch"})) {
std::string & arg = args.front();
// ...
continue;
}
if (sst::parse_opt(args,
"--shared",
sst::opt_arg::permitted,
&has_arg)) {
std::string arg = has_arg ? std::move(args.front()) : "group";
// ...
continue;
}
sst::unknown_opt(args);
}
if (directory_given) {
throw std::runtime_error("directory given twice");
}
directory = std::move(args.front());
directory_given = true;
}
std::cout << "ok\n";
} catch (std::exception const & e) {
try {
std::cerr << argv0 << ": " << e.what() << "\n";
} catch (...) {
}
return EXIT_FAILURE;
} catch (...) {
try {
std::cerr << argv0 << ": unknown error\n";
} catch (...) {
}
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
$ g++ cl_sst_parse_opt_git_init_example.cpp -lsst $ ./a.out ok $ ./a.out --quiet --initial-branch foo ok $ ./a.out --quiet --initial-branch=foo ok # "--initial-branch foo" and "--initial-branch=foo" are equivalent # because --initial-branch uses sst::opt_arg::required. $ ./a.out --quiet --initial-branch ./a.out: option requires an argument: --initial-branch $ ./a.out -q -b foo ok $ ./a.out -qbfoo ok # "-q -b foo", "-q -bfoo", and "-qbfoo" are equivalent because -q uses # sst::opt_arg::forbidden and -b uses sst::opt_arg::required. $ ./a.out -qb ./a.out: option requires an argument: -b $ ./a.out -qbfoo --bar=baz ./a.out: unknown option: --bar $ ./a.out -qbfoo -- --bar=baz ok # "--" is conventionally the options terminator (no further arguments # are options, even if they begin with "-" or "--"). $ ./a.out --shared=all . ok $ ./a.out --shared all . ./a.out: directory given twice # "--shared all" and "--shared=all" are not equivalent because --shared # uses sst::opt_arg::permitted, not sst::opt_arg::required.
3.26.35. The sst::unknown_opt function
#include <sst/catalog/unknown_opt.hpp>
namespace sst {
template<class StringList>
void unknown_opt(StringList const & args);
}
3.26.36. The sst::monostate class
#include <sst/catalog/monostate.hpp>
namespace sst {
struct monostate {};
}
This class was added to the library because std::monostate is not
available before C++17.
3.26.37. The sst::indeterminate_t tag class
#include <sst/catalog/indeterminate_t.hpp>
namespace sst {
struct indeterminate_t {};
}
3.26.38. The sst::indeterminate tag
#include <sst/catalog/indeterminate.hpp>
namespace sst {
SST_CPP17_INLINE constexpr sst::indeterminate_t indeterminate;
}
3.26.39. The sst::errno_error_string function
#include <sst/catalog/errno_error_string.hpp>
namespace sst {
std::string errno_error_string(int code);
std::string errno_error_string();
}
The sst::errno_error_string function returns a string representing the
errno value code.
Omitting code is equivalent to calling
sst::errno_error_string(errno).
If code is invalid, a generic error string will be returned.
3.26.40. The sst::errno_exception class
#include <sst/catalog/errno_exception.hpp>
namespace sst {
class errno_exception : public std::runtime_error {
public:
explicit errno_exception(std::string const & message, int code);
explicit errno_exception(char const * message, int code);
explicit errno_exception(std::string const & message);
explicit errno_exception(char const * message);
explicit errno_exception(int code);
explicit errno_exception();
int code() const noexcept;
};
}
-
If
messageis a null pointer, the behavior is undefined. -
Otherwise, if
messageis empty, it will be adjusted tosst::errno_error_string(code) + ".". -
Otherwise, if
messageends with(), it will be adjusted tomessage + " failed: " + sst::errno_error_string(code) + ".". -
Otherwise,
messagewill be adjusted tomessage + ": " + sst::errno_error_string(code) + ".".
Omitting code is equivalent to passing errno.
3.26.41. The sst::posix_gai_error_string function
#include <sst/catalog/posix_gai_error_string.hpp>
namespace sst {
std::string posix_gai_error_string(int code);
}
The sst::posix_gai_error_string function returns a string representing
the getaddrinfo error code code.
3.26.42. sst::is_negative
#include <sst/catalog/is_negative.hpp>
namespace sst {
template<sst::is_arithmetic_ish T>
constexpr bool is_negative(T const & x)
noexcept(noexcept(x < sst::zero<T>()));
}
The sst::is_negative function returns true if x is negative.
If T is an unsigned fundamental integer type[3], no compiler
warnings will be issued.
This can be useful in generic code, where an expression such as x < 0
can cause an “expression is always true” warning when the type of x
happens to be unsigned.
Writing sst::is_negative(x) instead of x < 0 will prevent such
warnings.
3.26.43. The sst::call_at_exit function
#include <sst/catalog/call_at_exit.hpp>
namespace sst {
void call_at_exit(void (*func)());
}
The sst::call_at_exit function registers the function pointed to
by func to be called when the main function returns or the
std::exit function is called.
If func is a null pointer, the behavior is undefined.
The functions will be called in reverse order of registration. If the same function is registered multiple times, it will be called multiple times. The total number of registrations is only limited by the available memory.
The behavior is undefined if any of the following occurs:
-
A function calls
std::_Exit,std::exit,std::longjmp,std::quick_exit, orsst::call_at_exit.
Any exceptions thrown by the functions will be caught and ignored.
The sst::call_at_exit function is thread-safe.
If concurrent calls are made, the functions will be registered properly,
but in an unspecified order.
Although the calls to the registered functions are sequential with
respect to each other, they are not necessarily sequential with respect
to any calls to static object destructors or functions registered with
the std::atexit function.
Because of this weak sequencing guarantee, if you need to access a
static data structure in func, you should not make the data structure
itself static, as this may cause a data race between the call to func
and the call to the data structure’s destructor.
Instead, you should keep a static pointer p to the data structure,
lazily allocating and constructing it under
if (p == nullptr) {} (if p is thread_local) or
std::call_once (if p is not thread_local),
and deallocating it in func under if (p != nullptr) {}.
3.26.44. The sst::preinit class
#include <sst/catalog/preinit.hpp>
namespace sst {
struct preinit {
template<class... Ts>
preinit(Ts &&...) {
}
};
}
The sst::preinit class accepts any arguments in its constructor
and does nothing.
This is primarily useful for running code at the beginning of a
member initializer list.
sst-example-54.cpp#include <sst/catalog/SST_ASSERT.h>
#include <sst/catalog/preinit.hpp>
class foo {
sst::preinit preinit_;
int x_;
public:
foo(int const x) : preinit_((SST_ASSERT((x > 0)), 0)), x_(x) {
}
};
int main() {
foo f(0);
return 0;
}
g++ sst-example-54.cpp -lsst
terminate called after throwing an instance of 'std::logic_error'
what(): sst-example-54.cpp:8: Assertion failed: (x > 0)
Aborted (core dumped)
3.26.45. The sst::to_hex function
The sst::to_hex function converts a sequence of bytes to a string.
3.26.45.1. The sst::to_hex function (overload 1)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Src,
class End,
class Dst,
sst::enable_if_t<
sst::is_byte_input_iterator<Src>::value
&& sst::is_sentinel<End, Src>::value
&& sst::is_output_iterator<Dst, char>::value
> = 0>
Dst to_hex(
Src src,
End const & end,
Dst dst,
sst::to_hex_options const & options = {}
);
}
The sst::to_hex function (overload 1) converts a sequence of bytes to a hex string.
Each byte will be converted to exactly two hex digits.
Src should satisfy sst::is_byte_input_iterator<Src>.
In other words, *src++ should read in successive
elements of the input sequence.
End should satisfy
sst::is_sentinel<End, Src>.
In other words, src == end should indicate
one-past-the-end of the input sequence.
Dst should satisfy
sst::is_output_iterator<Dst, char>.
In other words, *dst++ = x should write
out successive elements of the output sequence, where x
has type char.
The options parameter controls the output style.
-
options.prefix()indicates whether to add a0xprefix to the output. The prefix will be added even if the input sequence is empty. The default isfalse. -
options.uppercase_digits()indicates whether to useAtoFinstead ofatoffor digit values 10 to 15. The default istrue. -
options.uppercase_prefix()indicates whether to use0Xinstead of0xwhenoptions.prefix()istrue. The default isfalse.
3.26.45.2. The sst::to_hex function (overload 2)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Dst = std::string,
class Src,
class End,
sst::enable_if_t<
sst::is_byte_input_iterator<Src>::value
&& sst::is_sentinel<End, Src>::value
> = 0>
Dst to_hex(
Src src,
End const & end,
sst::to_hex_options const & options = {}
);
}
3.26.45.3. The sst::to_hex function (overload 3)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Src,
class End,
class Dst,
sst::enable_if_t<
sst::is_byte_input_iterator<Src>::value
&& sst::is_value_sentinel<End, Src>::value
&& sst::is_output_iterator<Dst, char>::value
> = 0>
Dst to_hex(
Src src,
End end,
Dst dst,
sst::to_hex_options const & options = {}
);
}
3.26.45.4. The sst::to_hex function (overload 4)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Dst = std::string,
class Src,
class End,
sst::enable_if_t<
sst::is_byte_input_iterator<Src>::value
&& sst::is_value_sentinel<End, Src>::value
> = 0>
Dst to_hex(
Src src,
End const & end,
sst::to_hex_options const & options = {}
);
}
3.26.45.5. The sst::to_hex function (overload 5)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Dst = std::string,
class Src,
sst::enable_if_t<
sst::is_byte_input_iterator<Src>::value
> = 0>
Dst to_hex(
Src src,
sst::to_hex_options const & options = {}
);
}
3.26.45.6. The sst::to_hex function (overload 6)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Src,
class Dst,
sst::enable_if_t<
sst::is_byte_input_iterable<Src>::value
&& sst::is_output_iterator<Dst, char>::value
> = 0>
Dst to_hex(
Src const & src,
Dst dst,
sst::to_hex_options const & options = {}
);
}
3.26.45.7. The sst::to_hex function (overload 7)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Dst = std::string,
class Src,
sst::enable_if_t<
sst::is_byte_input_iterable<Src>::value
> = 0>
Dst to_hex(
Src const & src,
sst::to_hex_options const & options = {}
);
}
3.26.45.8. The sst::to_hex function (overload 8)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Src,
class Dst,
sst::enable_if_t<
sst::is_byte<Src>::value
&& sst::is_output_iterator<Dst, char>::value
> = 0>
Dst to_hex(
Src src,
Dst dst,
sst::to_hex_options const & options = {}
);
}
3.26.45.9. The sst::to_hex function (overload 9)
#include <sst/catalog/to_hex.hpp>
namespace sst {
template<
class Dst = std::string,
class Src,
sst::enable_if_t<
sst::is_byte<Src>::value
> = 0>
Dst to_hex(
Src src,
sst::to_hex_options const & options = {}
);
}
3.26.48. The sst::unsigned_ceil_div function
The sst::unsigned_ceil_div function returns
\(\lceil \mathtt{a} / \mathtt{b} \rceil\)
for various type combinations of a and b.
If a is negative, b is negative, or b is zero, the behavior is
undefined.
3.26.48.1. Synopsis
#include <sst/catalog/unsigned_ceil_div.hpp>
namespace sst {
constexpr R unsigned_ceil_div(sst::is_integer a,
sst::is_integer b) noexcept;
}
3.26.48.2. The sst::unsigned_ceil_div function (overload 1)
#include <sst/catalog/unsigned_ceil_div.hpp>
namespace sst {
constexpr R unsigned_ceil_div(sst::is_integer a,
sst::is_integer b) noexcept;
}
The sst::unsigned_ceil_div function (overload 1) returns
\(\lceil \mathtt{a} / \mathtt{b} \rceil\),
where a and b are fundamental integers[3].
If a is negative or b is not positive, the behavior is undefined.
By default, the return type R is the same as the type of the
expression a/b, but it can be overridden by providing a type as a
template parameter, in which case the return value will be
explicitly converted to that type.
For example,
sst::unsigned_ceil_div(9, 4L)
will return 3L, while
sst::unsigned_ceil_div<int>(9, 4L)
will return 3.
3.26.49. The sst::unsigned_max function
#include <sst/catalog/unsigned_max.hpp>
namespace sst {
template<
class X = D,
sst::is_arithmetic_ish Arg1,
sst::is_arithmetic_ish... Args>
constexpr R unsigned_max(Arg1 && arg1, Args &&... args) noexcept(E);
}
The sst::unsigned_max function returns the maximum of its
arguments.
If any argument is negative, the behavior is undefined.
D is an unspecified type that is internal to the library.
If the template parameter X is left defaulted to D, the return
type R will be
sst::common_type_t<sst::remove_cvref_t<Args>...>.
Note that the result can always be represented in this type.
Otherwise, the return type R will be sst::remove_cvref_t<X>,
and if the result cannot be represented in this type, the
behavior is undefined.
If all arguments are fundamental integers[3], constexpr will hold
and E will be true.
3.26.50. The sst::unsigned_min function
#include <sst/catalog/unsigned_min.hpp>
namespace sst {
template<
class X = D,
sst::is_arithmetic_ish Arg1,
sst::is_arithmetic_ish... Args>
constexpr R unsigned_min(Arg1 && arg1, Args &&... args) noexcept(E);
}
The sst::unsigned_min function returns the minimum of its
arguments.
If any argument is negative, the behavior is undefined.
D is an unspecified type that is internal to the library.
If the template parameter X is left defaulted to D, the return
type R will be
sst::common_type_t<sst::remove_cvref_t<Args>...>.
Note that the result can always be represented in this type.
Otherwise, the return type R will be sst::remove_cvref_t<X>,
and if the result cannot be represented in this type, the
behavior is undefined.
If all arguments are fundamental integers[3], constexpr will hold
and E will be true.
3.26.51. sst::unsigned_rand_range_cc
The sst::unsigned_rand_range_cc function returns a uniform random
value from a left-closed, right-closed range of nonnegative integers.
3.26.51.1. Synopsis
#include <sst/catalog/unsigned_rand_range_cc.hpp>
namespace sst {
template<sst::is_integer T>
T unsigned_rand_range_cc(sst::is_urbg & g);
template<sst::is_integer T>
T unsigned_rand_range_cc();
}
3.26.51.2. Overload 1
#include <sst/catalog/unsigned_rand_range_cc.hpp>
namespace sst {
template<sst::is_integer T>
T unsigned_rand_range_cc(sst::is_urbg & g);
}
The sst::unsigned_rand_range_cc function (overload 1) returns a uniform
random value from the complete nonnegative range of T using g as the
randomness source.
Any cvref-qualifiers on T are removed.
3.26.51.3. Overload 2
#include <sst/catalog/unsigned_rand_range_cc.hpp>
namespace sst {
template<sst::is_integer T>
T unsigned_rand_range_cc();
}
The sst::unsigned_rand_range_cc function (overload 2) returns a uniform
random value from the complete nonnegative range of T using
sst::crypto_rng() as the randomness source.
Any cvref-qualifiers on T are removed.
sst-example-55.cpp#include <iomanip>
#include <iostream>
#include <sst/catalog/unsigned_rand_range_cc.hpp>
int main() {
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
if (j > 0) {
std::cout << " ";
}
auto const x = sst::unsigned_rand_range_cc<unsigned char>();
auto const y = static_cast<unsigned int>(x);
std::cout << std::setw(3) << y;
}
std::cout << "\n";
}
return 0;
}
136 147 227 221 40 234 203 127 49 188 110 192 192 116 29 62 27 132 75 140 80 46 226 179 53 106 43 69 218 51 100 224 225 101 108 242 81 123 182 99 90 194 62 87 84 193 130 20 144 24 49 49 0 228 46 168 61 155 32 16 42 158 107 69 247 212 229 154 36 237 60 109 146 129 180 188 152 255 49 66 192 213 182 209 120 24 44 113 246 151 248 133 150 187 47 245 228 242 53 119
3.26.52. sst::unsigned_rand_range_co
The sst::unsigned_rand_range_co function returns a uniform random
value from a left-closed, right-open range of nonnegative integers.
3.26.52.1. Synopsis
#include <sst/catalog/unsigned_rand_range_co.hpp>
namespace sst {
// TODO
}
3.26.53. sst::unsigned_rand_range_oc
The sst::unsigned_rand_range_oc function returns a uniform random
value from a left-open, right-closed range of nonnegative integers.
3.26.53.1. Synopsis
#include <sst/catalog/unsigned_rand_range_oc.hpp>
namespace sst {
// TODO
}
3.26.54. sst::unsigned_rand_range_oo
The sst::unsigned_rand_range_oo function returns a uniform random
value from a left-open, right-open range of nonnegative integers.
3.26.54.1. Synopsis
#include <sst/catalog/unsigned_rand_range_oo.hpp>
namespace sst {
// TODO
}
3.26.55. The sst::last_arg function
#include <sst/catalog/last_arg.hpp>
namespace sst {
template<std::size_t I = 1, class First, class... Rest>
constexpr R last_arg(First && first, Rest &&... rest);
}
The sst::last_arg function returns its I`th argument, counting
from right to left starting with 1.
The behavior is as if the selected parameter were declared as
`Arg && arg and returned as std::forward<Arg>(arg).
3.26.56. The sst::numeric_limits alias
#include <sst/catalog/numeric_limits.hpp>
namespace sst {
template<class T>
using numeric_limits = std::numeric_limits<sst::remove_cvref_t<T>>;
}
The sst::numeric_limits alias is a convenience alias for
std::numeric_limits that ignores any references and
cv-qualifiers on T.
3.26.57. sst::checked_overflow
#include <sst/catalog/checked_overflow.hpp>
namespace sst {
class checked_overflow : public std::overflow_error {
public:
using std::overflow_error::overflow_error;
}; //
}
3.26.58. sst::zero
#include <sst/catalog/zero.hpp>
namespace sst {
template<
class T,
sst::enable_if_t<
sst::is_arithmetic_like<T>::value
> = 0>
consteval sst::remove_cvref_t<T> zero() noexcept;
template<
class T,
sst::enable_if_t<
!sst::is_arithmetic_like<T>::value
&& sst::is_arithmetic_ish<T>::value
> = 0>
constexpr R zero() noexcept(B);
}
3.26.59. The sst::in_place_t tag dispatch structure
#include <sst/catalog/in_place_t.hpp>
namespace sst {
struct in_place_t {};
}
The sst::in_place_t tag dispatch structure is used to indicate that
an object should be constructed in-place.
The
sst::in_place_t
tag dispatch structure
was added to the library because the
std::in_place_t
tag dispatch structure
is not available below
C++17.
3.26.60. The sst::in_place tag dispatch constant
#include <sst/catalog/in_place.hpp>
namespace sst {
SST_CPP17_INLINE constexpr sst::in_place_t in_place;
}
The sst::in_place tag dispatch constant corresponds to the
sst::in_place_t tag dispatch structure.
3.26.61. SST_NARGS
#include <sst/catalog/SST_NARGS.h>
#define SST_NARGS(...) n
The SST_NARGS macro expands to the number of arguments that were
passed to it, formatted as an unsuffixed decimal integer constant.
If no arguments are given and the language version is below C23 or C++20, the behavior is undefined.
sst-example-56.c or sst-example-56.cpp#include <sst/catalog/SST_C23_OR_LATER.h>
#include <sst/catalog/SST_CPP20_OR_LATER.h>
#include <sst/catalog/SST_NARGS.h>
#if __cplusplus
#include <cstdio>
using std::puts;
#else
#include <stdio.h>
#endif
#define STR2(X) #X
#define STR1(X) STR2(X)
#define F(...) \
puts("SST_NARGS(" #__VA_ARGS__ ") = " STR1(SST_NARGS(__VA_ARGS__)))
int main() {
#if SST_C23_OR_LATER || SST_CPP20_OR_LATER
F();
#endif
F(a);
F(a, b);
F(a, b, c);
return 0;
}
3.26.62. SST_DEFER
#include <sst/catalog/SST_DEFER.h>
#define SST_DEFER /*...*/
The SST_DEFER macro defers the expansion of a function-like macro
call until the expansion of the nearest enclosing call to the
SST_EXPAND macro.
To defer a function-like macro call F(x), write the call as
SST_DEFER(F)(x) instead.
You must also define an auxiliary object-like macro named F_DEFER that
simply expands to F (i.e., #define F_DEFER F).
3.26.63. The SST_EXPAND macro
#include <sst/catalog/SST_EXPAND.h>
#define SST_EXPAND(...) __VA_ARGS__
The SST_EXPAND macro expands to its argument list unchanged.
Note that calling the SST_EXPAND macro without any arguments,
i.e., writing SST_EXPAND(), is well-defined even when
__VA_OPT__ is not supported.
In this case, the call is interpreted as having one argument that
consists of no preprocessing tokens.
Because of the way the preprocessor works, macro arguments that contain commas must be enclosed in parentheses, otherwise the commas will be interpreted as macro argument separators. If the argument is an expression, then the extra parentheses are harmless, but if the argument is something else, then the extra parentheses will generally cause a syntax error.
For example, if F(T) is a macro that takes a type name T, then
F(std::map<int, int>) won’t work as expected, as the comma is
interpreted as a macro argument separator and the call is therefore
trying to pass two arguments: std::map<int and int>.
Writing F((std::map<int, int>)) fixes the argument count
issue, but now the type name is enclosed in parentheses, which will
generally cause a syntax error.
One way to resolve this is to declare a type alias for
std::map<int, int> and pass the alias to the macro.
However, this is not a general solution, as it only works in the
specific case where the argument is a type name.
A general way to resolve this is to require the arguments to always be
enclosed in parentheses and use the SST_EXPAND macro to remove
the parentheses.
sst-example-57.cpp#include <iostream>
#include <map>
#include <type_traits>
#include <sst/catalog/SST_EXPAND.h>
// When calling this macro, each argument should always be enclosed in
// parentheses, which SST_EXPAND will then remove.
#define SAME(A, B) (std::is_same<SST_EXPAND A, SST_EXPAND B>::value)
int main() {
std::cout << SAME((std::map<int, int>), (std::map<int, int>)) << "\n";
return 0;
}
1
3.26.64. sstSeqHashCore
A class H satisfies the sstSeqHashCore requirement if all
of the following hold:
-
Hsatisfies the following class description:class H { public: // Default operations H() noexcept; // default constructor H(H const &); // copy constructor H & operator=(H const &); // copy assignment H(H &&) noexcept; // move constructor H & operator=(H &&) noexcept; // move assignment ~H() noexcept; // destructor template<class T> class is_input; using output_t = /*...*/; // Mutators H & clear() noexcept; H & init(); H & update(sst::is_input_iterator<is_input> src, sst::is_integer_ish const & len); H & update(sst::is_input_iterator<is_input> src, sst::is_sentinel<src> const & end); H & update(sst::is_input_iterator<is_input> src, sst::is_value_sentinel<src> const & end); H & finish(); // Getters output_t const & output() const & noexcept; output_t && output() && noexcept; }; -
All mutator functions return
*this.
The state of H changes according to the following diagram:
3.26.65. sst::value_sentinel
#include <sst/catalog/value_sentinel.hpp>
namespace sst {
template<class Value>
constexpr sst::value_sentinel_t<sst::remove_cvref_t<Value>>
value_sentinel(Value && value);
}
3.26.66. sst::value_sentinel_t
#include <sst/catalog/value_sentinel_t.hpp>
namespace sst {
template<class Value>
struct value_sentinel_t {
Value value;
friend constexpr bool operator==(
value_sentinel_t const & a,
Value const & b
);
friend constexpr bool operator==(
Value const & a,
value_sentinel_t const & b
);
friend constexpr bool operator!=(
value_sentinel_t const & a,
Value const & b
);
friend constexpr bool operator!=(
Value const & a,
value_sentinel_t const & b
);
};
}
The sst::value_sentinel_t structure is used to disambiguate a
count parameter vs. a value sentinel parameter.
For example, consider the call sst::sha256(p, 5).
Does this mean hash 5 bytes from p, or hash bytes from p until we
terminate by seeing a byte with value 5?
By convention, it means the former, and the latter must instead be
written as sst::sha256(p, sst::value_sentinel(5)).
3.26.67. SST_REVERSE
#include <sst/catalog/SST_REVERSE.h>
#define SST_REVERSE(...) /*...*/
The SST_REVERSE macro expands to a comma-separated list of its
arguments in reverse order.
3.26.68. The SST_WITH_NOEXCEPT feature test macro
#include <sst/catalog/SST_WITH_NOEXCEPT.h>
// or: <sst/catalog/SST_WITH_NOEXCEPT.hpp>
#define SST_WITH_NOEXCEPT /*...*/
The SST_WITH_NOEXCEPT feature test macro indicates whether the
noexcept operator and the noexcept specifier are
safe to use.
Some versions of some compilers have bugs with these constructs, in
which case it is best not to use them.
The macro expands to an integer constant expression with type int
whose value is 1 to mean true and 0 to mean false.
The expression is either parenthesized or exactly 1 or 0.
The expression is also suitable for use in the preprocessor.
3.26.69. sst::unsigned_mod
#include <sst/catalog/unsigned_mod.hpp>
sst::unsigned_mod(x, m)
The sst::unsigned_mod function returns the least nonnegative residue
of x modulo m.
x may have any integer-ish type X.
m may have any integer-ish type M.
m must be positive.
x must be nonnegative.
If your x may be negative, you should use sst::mod instead of
this function.
If X and M are not just integer-ish but in fact
integer-like, then the function will be constexpr and
noexcept.
The return value will have type M.
Alternatively, you can specify a single template parameter to convert
the return value to a specific type.
For example, sst::unsigned_mod<int>(8L, 5L) will return 3
instead of 3L.
If the conversion is not noexcept, it will remove any
noexcept from the function.
3.26.70. sst::mod
#include <sst/catalog/mod.hpp>
sst::mod(x, m)
The sst::mod function returns the least nonnegative residue of x
modulo m.
x may have any integer-ish type X.
m may have any integer-ish type M.
m must be positive.
If your x is always nonnegative, you may want to use
sst::unsigned_mod instead of this function, as it may give better
performance.
If X and M are not just integer-ish but in fact
integer-like, then the function will be constexpr and
noexcept.
3.27. Hash functions
3.27.1. The sst::sha256 function
#include <sst/catalog/sha256.hpp>
namespace sst {
// 1
template<
class Src,
sst::enable_if_t<
(
sst::is_iterable<Src, sst::is_byte>::value // a
|| sst::is_input_iterator<Src, sst::is_byte>::value // b
)
> = 0>
std::vector<unsigned char> sha256(Src && src);
// 2
template<
class Src,
sst::enable_if_t<
(
sst::is_iterable<Src, sst::is_byte>::value // a
|| sst::is_input_iterator<Src, sst::is_byte>::value // b
) && (
sst::is_integer_ish<End>::value // c
|| sst::is_sentinel<End, Src>::value // d
|| sst::is_value_sentinel<End, Src>::value // e
)
> = 0>
std::vector<unsigned char> sha256(Src && src, End const & end);
}
The sst::sha256 function computes and returns the SHA-256 hash of
the byte sequence (a) stored by or (b) iterated by src.
The byte sequence consists of:
-
(1a) All bytes stored by
src. -
(1b) All bytes iterated by
srcup to but not including the first zero byte. -
(c) The first
endbytes (a) stored by or (b) iterated bysrc. -
(d) All bytes (a) stored by or (b) iterated by
srcup to but not including the first iterator that compares equal toend. -
(e) All bytes (a) stored by or (b) iterated by
srcup to but not including the first byte that compares equal toend.
For (a), src will be treated as if it had type
sst::remove_cvref_t<Src> const & regardless of its actual type.
For (b), an iterator will be constructed from src via
sst::remove_cvref_t<Src>(std::forward<Src>(src)) and then
iterated with no further copies or moves.
sst-example-58.cpp#include <iostream>
#include <sst/catalog/sha256.hpp>
#include <sst/catalog/to_hex.hpp>
namespace {
template<class Label, class Hash>
void f(Label const & label, Hash const & hash) {
std::cout << label;
std::cout << sst::to_hex(hash);
std::cout << "\n";
}
}
int main() {
char const s[] = "Stealth";
auto const v = sst::value_sentinel('h');
f("1a (Stealth): ", sst::sha256(s));
f("2ac (Ste): ", sst::sha256(s, 3));
f("2ad (Steal): ", sst::sha256(s, &s[5]));
f("2ae (Stealt): ", sst::sha256(s, v));
f("2b (tealth): ", sst::sha256(&s[1]));
f("2bc (tea): ", sst::sha256(&s[1], 3));
f("2bd (teal): ", sst::sha256(&s[1], &s[5]));
f("2be (tealt): ", sst::sha256(&s[1], v));
return 0;
}
g++ sst-example-58.cpp -lsst
1a (Stealth): 526A40A447DDD7AA52D34BB62DBF1DA04DC4ABA8403769D239ADE80893FFEF7A 2ac (Ste): 25BD152797157817E497C23F90BA70D3D327F2F3721B030BFD9294CE10B61E85 2ad (Steal): E2380ED2FB11F5D22C72FF91103478BBC2329BF16FAE4243F68FC796904B936F 2ae (Stealt): D6973DF4D6C5CD8C3D368DD9CC8E1E8705215C2ED8D0353C697C3A0C3EF58CDE 2b (tealth): BC73F662B72CCC96E8AFD6182411CA385A00CE0AB3C99F746824A16FDA451BF4 2bc (tea): A9F74D1EC36EBDEB2DA3F6E5868090CD2A2D20B3DCCA7B62F60304B1D3D9EF42 2bd (teal): 2655399ACF997BC2AD5346ECA205A8B1945E74831D4AAC71CAFBCFE2A73F093E 2be (tealt): 883B33A24036790D3DF3CC1900D5EB2B50EC20FA80DF803C8B4CE6DE132B6CCE
3.28. SQLite utilities
3.28.1. The sst::sqlite::database class
#include <sst/catalog/sqlite/database.hpp>
namespace sst {
class database {
public:
database & operator=(
database const & other
);
database & deserialize(
char const * schema,
unsigned char * buffer,
sqlite3_int64 size,
bool readonly = false,
bool copy = true,
bool resizable = true,
sqlite3_int64 capacity = 0,
bool deallocate = false
);
database & deserialize(
char const * schema,
unsigned char const * buffer,
sqlite3_int64 size,
bool readonly = false,
bool copy = true,
bool resizable = true,
sqlite3_int64 capacity = 0,
bool deallocate = false
);
template<
class Size,
sst::enable_if_t<
sst::is_integer_ish<Size>::value
> = 0>
database & deserialize(
char const * schema,
unsigned char const * buffer,
Size const & size
);
template<
class Buffer,
sst::enable_if_t<
sst::is_iterable<Buffer, sst::is_byte>::value
&& sst::is_contiguous<Buffer>::value
> = 0>
database & deserialize(
char const * schema,
Buffer const & buffer
);
std::vector<unsigned char> serialize(
char const * schema
);
};
}
3.28.1.1. Copy assignment
Copy assignment overwrites *this with other as follows:
-
For each database that exists in both
*thisandother, the database in*thisis overwritten with the database fromother. Themaindatabase always exists, so this step always occurs for themaindatabase. No other databases always exist, not even thetempdatabase, which only comes into existence upon first use. -
For each database that exists only in
other, a new:memory:database is attached to*thisand overwritten with the database fromother. However, if the database in question is thetempdatabase, then it cannot be attached, so it will instead be brought into existence by executing aCREATE TEMP TABLEstatement before being overwritten. -
For each database that exists only in
*this, the database is detached from*this. However, if the database in question is thetempdatabase, then it cannot be detached, so it will instead have all of its entities dropped.
3.28.1.2. The deserialize function (overload 1)
database & deserialize(
char const * schema,
unsigned char * buffer,
sqlite3_int64 size,
bool readonly = false,
bool copy = true,
bool resizable = true,
sqlite3_int64 capacity = 0,
bool deallocate = false
);
The deserialize function (overload 1)
attaches the schema name to the database serialization that consists
of the first size bytes in buffer.
If schema is "temp", then an exception will be thrown.
If schema already names a database, then it will be closed before
attaching it to the database serialization.
This will occur even if schema is "main", which cannot normally be
closed.
If readonly is true, then the database will be read-only.
If copy is true, then a copy of buffer will be allocated to
underpin the database, and the copy will be automatically deallocated
when the database is closed.
Otherwise, buffer itself will underpin the database.
In this case, the caller must ensure that buffer continues to exist
and is not externally modified until the database is closed.
If readonly is true, then resizable is ignored.
Otherwise, resizable specifies whether buffer will be automatically
reallocated when more capacity is needed.
In this case, either copy must be true or buffer must be allocated
via SQLite.
If readonly is true, then capacity is ignored.
Otherwise, capacity must be either zero or at least as large as
size, and zero will be automatically adjusted to size.
In this case, if copy is true, then capacity specifies how large
the copy of buffer should be, although only the first size bytes
will actually be copied.
Otherwise, if copy is false, then capacity specifies how many
bytes are actually available for use in buffer, which may be more than
size.
If copy is true, then deallocate is ignored.
Otherwise, deallocate specifies whether buffer will be automatically
deallocated when the database is closed.
If so, then buffer must be allocated via SQLite.
When enabled, automatic deallocation will always occur, even if this
function itself throws an exception.
This function always returns *this.
3.28.1.3. The deserialize function (overload 2)
database & deserialize(
char const * schema,
unsigned char const * buffer,
sqlite3_int64 size,
bool readonly = false,
bool copy = true,
bool resizable = true,
sqlite3_int64 capacity = 0,
bool deallocate = false
);
The deserialize function (overload 2) is
equivalent to the
deserialize function (overload 1) except at
least one of readonly and copy must be true.
3.28.1.4. The deserialize function (overload 3)
template<
class Size,
sst::enable_if_t<
sst::is_integer_ish<Size>::value
> = 0>
database & deserialize(
char const * schema,
unsigned char const * buffer,
Size const & size
);
The deserialize function (overload 3) is
equivalent to the
deserialize function (overload 1) except the
size parameter may be any integer-ish type.
3.28.1.5. The deserialize function (overload 4)
template<
class Buffer,
sst::enable_if_t<
sst::is_iterable<Buffer, sst::is_byte>::value
&& sst::is_contiguous<Buffer>::value
> = 0>
database & deserialize(
char const * schema,
Buffer const & buffer
);
3.28.1.6. The serialize function (overload 1)
std::vector<unsigned char> serialize(
char const * schema
);
3.29. Tracing utilities
3.29.1. The SST_TEV_BOT macro
#include <sst/catalog/SST_TEV_BOT.hpp>
#define SST_TEV_BOT(tev) /*...*/
3.29.2. The SST_TEV_TOP macro
#include <sst/catalog/SST_TEV_TOP.hpp>
#define SST_TEV_TOP(tev) /*...*/
sst-example-59.cpp#include <iostream>
#include <stdexcept>
#include <sst/catalog/SST_TEV_ARG.hpp>
#include <sst/catalog/SST_TEV_BOT.hpp>
#include <sst/catalog/SST_TEV_DEF.hpp>
#include <sst/catalog/SST_TEV_TOP.hpp>
#include <sst/catalog/tracing_event.hpp>
#include <sst/catalog/tracing_exception.hpp>
#include <nlohmann/json.hpp>
namespace {
using tev_t = sst::tracing_event<nlohmann::json>;
using tex_t = sst::tracing_exception<tev_t>;
void f(tev_t tev) {
SST_TEV_TOP(tev);
throw std::runtime_error("Something bad happened");
SST_TEV_BOT(tev);
}
} // namespace
int main() {
tev_t SST_TEV_DEF(tev);
try {
f(SST_TEV_ARG(tev));
} catch (tex_t const & e) {
try {
std::cerr << "Tracing event: ";
if (e.tev().json()) {
std::cerr << *e.tev().json();
} else {
std::cerr << "{}";
}
std::cerr << "\n";
} catch (...) {
}
}
}
3.30. Serialization
3.30.1. sst::i2osp
#include <sst/catalog/i2osp.hpp>
sst::i2osp(src, len, [dst])
The sst::i2osp function converts a nonnegative integer src to a big
endian octet string of length len.
This is an implementation of the I2OSP (integer to octet string
primitive) function from IETF RFC 8017.
src may have any integer-ish type.
len may have any integer-ish type.
dst may be any output iterator that accepts unsigned char.
If dst is given, the function writes the len octets to dst and
returns one past the end of dst.
If dst is omitted, the function returns a std::vector<unsigned
char> of length len that holds the octets.
If len octets are not enough to represent src, an exception will be
thrown.
3.30.2. sst::os2ip
#include <sst/catalog/os2ip.hpp>
sst::os2ip<Dst>(src, [end])
The sst::os2ip function converts a big endian octet string src to a
nonnegative integer.
This is an implementation of the OS2IP (octet string to integer
primitive) function from IETF RFC 8017.
Dst may be any integer-ish type.
src may be a byte input iterator or an iterable byte container.
An iterable byte container will be implicitly adjusted to a byte input
iterator starting at the first byte.
end may be a sentinel for src, a value sentinel for src, or an
integer-ish count of the number of octets to read.
end may only be omitted if src is an iterable byte container, in
which case end will be implicitly taken to be one past the end of the
container.
The function returns the nonnegative integer value with type Dst.
If Dst does not have enough range to represent the integer value, an
exception will be thrown.
4. Java library
4.1. Assertions
This is the simplest but always evaluates g(x) and always causes a
call to SST_ASSERT:
void f(final Object x) {
SST_ASSERT(g(x));
}
This omits the evaluation of g(x) but still always causes a call to
SST_ASSERT:
void f(final Object x) {
SST_ASSERT(SST_NDEBUG || g(x));
}
This omits the evaluation of g(x) and the call to SST_ASSERT since
SST_NDEBUG is static and final (see JLS 7 §13.4.9):
void f(final Object x) {
if (!SST_NDEBUG) {
SST_ASSERT(g(x));
}
}
In Java 7, you can make exceptions thrown by g(x) also trigger an
assertion like this:
void f(final Object x) {
if (!SST_NDEBUG) {
try {
SST_ASSERT(g(x));
} catch (final Throwable e) {
SST_ASSERT(e);
}
}
}
Or like this:
void f(final Object x) {
if (!SST_NDEBUG) {
SST_ASSERT(new ThrowingRunnable<Throwable>() {
@Override
public final void run() throws Throwable {
SST_ASSERT(g(x));
}
});
}
}
In Java 8 or later, you can use a lambda:
void f(final Object x) {
if (!SST_NDEBUG) {
SST_ASSERT(() -> {
SST_ASSERT(g(x));
});
}
}
4.2. JSON processing
This example uses Gson as the underlying JSON parsing library, but
almost any library could be used.
The only requirement is that the library can parse a JSON value into a
hierarchy of
String,
Boolean,
Number,
List,
and
Map
objects.
Data.javaimport com.stealthsoftwareinc.sst.FromJson;
import com.stealthsoftwareinc.sst.Json;
import java.math.BigInteger;
import java.util.ArrayList;
public final class Data implements FromJson<Data> {
public int x = 0;
public BigInteger y = BigInteger.ZERO;
@Override
public final Data fromJson(final Object src) {
x = Json.getAs(src, "x", x);
y = Json.getAs(src, "y", y);
return this;
}
}
Main.javaimport com.google.gson.Gson;
import com.stealthsoftwareinc.sst.Json;
import com.stealthsoftwareinc.sst.ParseFailureStatus;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public final class Main {
public static final void main(final String... args) throws Exception {
try (final InputStreamReader stdin =
new InputStreamReader(System.in, StandardCharsets.UTF_8)) {
final Data d = new Data();
try {
Json.getTo(new Gson().fromJson(stdin, Map.class), d);
} catch (final ParseFailureStatus e) {
throw new ParseFailureStatus("<stdin>" + e.getMessage(), e);
}
}
}
}
4.3. The Arith class
package com.stealthsoftwareinc.sst;
public final class Arith {
private Arith();
}
4.3.1. The Arith.newtonSqrt method
public static BigDecimal newtonSqrt(BigDecimal x, int scale);
The Arith.newtonSqrt method computes an approximation of
\(\sqrt{\mathtt{x}}\) using Newton’s method.
scale specifies the number of fractional digits to use for internal
computations until a fixed point is reached.
A larger scale produces a more accurate result, but there is no
guarantee on how many digits of the result match the true digits of
\(\sqrt{\mathtt{x}}\).
4.4. The Modulus class
package com.stealthsoftwareinc.sst;
public final class Modulus {
// Constructors
public Modulus(long m);
public Modulus(BigInteger m);
// Value sizing
public boolean valuesFit(Byte T);
public boolean valuesFit(Short T);
public boolean valuesFit(Integer T);
public boolean valuesFit(Long T);
public boolean valuesFit(BigInteger T);
// Modulus retrieval
public byte get(Byte T);
public short get(Short T);
public int get(Integer T);
public long get(Long T);
public BigInteger get(BigInteger T);
}
The Modulus class represents a modulus that can be used for
modular arithmetic.
4.4.1. Constructors
public Modulus(long m);
public Modulus(BigInteger m);
4.4.2. Value sizing
public boolean valuesFit(Byte T);
public boolean valuesFit(Short T);
public boolean valuesFit(Integer T);
public boolean valuesFit(Long T);
public boolean valuesFit(BigInteger T);
The valuesFit method determines whether type T can represent all
modular values of \(m\).
The BigInteger overload always returns true.
Every other overload returns true if and only if
\(m \le 2^\mathtt{T.SIZE}\).
Note that Java uses two’s complement representation for byte,
short, int, and long, and T.SIZE is the number of width bits
in type T.
See Integer.SIZE, for example.
Because these types are signed, certain modular values are sometimes
stored as negative values.
For example,
\(2^{31} \pmod{2^{32}}\) and \(2^{32} - 1 \pmod{2^{32}}\)
are stored in type int as \(-2^{31}\) and \(-1\), respectively.
4.4.3. Modulus retrieval
public byte get(Byte T);
public short get(Short T);
public int get(Integer T);
public long get(Long T);
public BigInteger get(BigInteger T);
The get method returns the value of \(m\) in type T.
Since BigInteger can represent any integer,
get((BigInteger)null) always returns the exact value of
\(m\).
For byte, short, int, and long, if
\(m > 2^{\mathtt{T.SIZE}}\), i.e., if valuesFit(T) returns false,
the behavior of get(T) is undefined.
Otherwise, if \(m \ge 2^{\mathtt{T.SIZE} - 1}\), get(T) returns
\(-(2^\mathtt{T.SIZE} - m)\).
Otherwise, get(T) returns the exact value of \(m\).
4.5. The FixedPointModContext class
package com.stealthsoftwareinc.sst;
public final class FixedPointModContext {
}
The FixedPointModContext class converts between real numbers
and fixed-point modular representation.
4.5.1. The encode method
If the encoding of src is not representable under the modulus and
checked is true, an exception will be thrown.
If the encoding of src is not representable under the modulus and
checked is false, the behavior is undefined.
4.5.2. The decode method
If src is not a residue of the modulus, the behavior is undefined.
If the decoding of src is not representable in dstType and checked
is true, an exception will be thrown.
If the decoding of src is not representable in dstType and checked
is false, the behavior is undefined.
5. JavaScript library
5.1. Feature testing utilities
5.1.1. sst.bootstrap_css_version
import {} from "./sst/catalog/bootstrap_css_version.mjs";
async sst.bootstrap_css_version([options = {}])
The sst.bootstrap_css_version function searches for a Bootstrap CSS
file and returns a Promise that resolves to the version number
of the file.
If no Bootstrap CSS file is found, the returned Promise will
resolve to null.
Otherwise, it will resolve to a string that contains the version number
of the first Bootstrap CSS file found.
For example, for Bootstrap 5.3.2, the string will be "5.3.2".
The first call to this function will cache its result, and subsequent
calls will return the cached result.
This behavior can be changed using
options.recache.
The
options parameter supports the
following properties:
recache-
The function will behave as if this call was the first call. Any previously cached result will be overwritten with the new result.
5.2. Type traits
5.2.1. sst.is_integer_ish
import {} from "./sst/catalog/is_integer_ish.mjs";
sst.is_integer_ish(x)
The sst.is_integer_ish function returns true if x
is a primitive safe integer or a primitive
BigInt, or false if not.
5.2.2. sst.is_json
import {} from "./sst/catalog/is_json.mjs";
sst.is_json(x)
The sst.is_json function returns true if x is a JSON
value, or false if not.
A JSON value is any of the following:
-
The
nullvalue. -
A plain array whose elements are also JSON values.
-
A plain object whose properties are also JSON values.
5.3. sst.barf
import {} from "./sst/catalog/barf.mjs";
sst.barf([message])
The sst.barf function outputs an error message and terminates the
program to the greatest extent supported by the runtime environment.
5.4. sst.chunkwise
import {} from "./sst/catalog/chunkwise.mjs";
async sst.chunkwise(src, f, [options={}])
The sst.chunkwise function reads a stream of chunks from src,
calling the f callback on each chunk.
The return value is a Promise that resolves to
undefined.
The f callback will be called as f(chunk) for each chunk.
If f returns a Promise, it will be awaited.
The following types are supported for src:
Blob-
The blob will be read as a stream of
Uint8Arraychunks. File(browser only)-
The file will be read as a stream of
Uint8Arraychunks. fsp.FileHandle(Node.js only)-
The file will be read as a stream of
Uint8Arraychunks. fsp.ReadStream(Node.js only)-
The file will be read as a stream of
Uint8Arraychunks. ReadableStream-
The stream of chunks will be read by calling
src.getReader()to get areader, then callingreader.read()repeatedly. Eachchunkwith typeArrayBufferwill be adjusted to aUint8Array(chunk)view. - string (Node.js only)
-
srcwill be opened as a file viafsp.open(src, "r"), and the file will be read as a stream ofUint8Arraychunks. - Any other type
-
srcitself will be considered to be the only chunk in the stream. Ifsrchas typeArrayBuffer, it will be adjusted to aUint8Array(src)view.
The following options are supported:
fetch(optional)-
Options to pass to the
sst.fetchfunction. The presence of this option changes the behavior of thesst.chunkwisefunction as follows:-
srcmust be a string. -
sst.fetch(src, options.fetch)will be called, and the response body will be read as a stream ofUint8Arraychunks.
-
5.5. sst.crypto_rng
import {} from "./sst/catalog/crypto_rng.mjs";
sst.crypto_rng(dst, [options = {}])
The sst.crypto_rng function generates cryptographically secure
random bytes.
dst may be any of the following:
-
A nonnegative primitive safe integer
Number.The function will create a new
Uint8Arraywith lengthdstand fill it with random bytes.The return value will be the new
Uint8Array. -
A nonnegative primitive
BigInt.The function will create a new
Uint8Arraywith lengthdstand fill it with random bytes.The return value will be the new
Uint8Array. -
A
TypedArray.The function will fill the array with random bytes.
The return value will be
dst. -
An array
[x, i, n]wherexis a typed array andiandnare (big) integers.The function will fill the
nelements ofxbeginning withx[i]with random bytes. Ifnis zero, no random bytes will be generated, butimust still be valid.The return value will be
x.
options may
contain the following members:
async(optional)-
A boolean that indicates whether the function should perform its work asynchronously.
If this is
false, the function will perform its work synchronously.If this is
true, the function will perform its work asynchronously and return aPromisethat resolves to the synchronous return value instead of returning the synchronous return value directly.By default, this is
false. crypto(optional)-
The instance of the Web Cryptography API to use.
5.6. sst.debounce
import {} from "./sst/catalog/debounce.mjs";
sst.debounce([init], proc, [delay=1000])
The sst.debounce function returns an async function f that can
be used as a debounced handler for an event.
The proc callback should perform the debounced work.
Instead of being called once for each call to f, it will only be
called after the most recent call to f becomes delay milliseconds
old.
The init callback, if given, will be called by f each time f is
called.
It can be used to perform any non-debounced work.
No calls to init or proc will ever overlap, even if they use
await.
In other words, at any given moment, at most one execution context will
exist for init and proc, even if that execution context is currently
suspended by an await.
Conceptually, each call to f causes a direct call to init and
possibly a delayed call to proc.
If the proc call occurs, it is guaranteed to occur after the init
call for the same call to f.
proc will never be called directly by f, even if delay is 0.
In other words, proc will only be called after f returns.
init and proc will be passed an initial parameter named canceler.
In init, canceler will be undefined, as it is only passed to be
consistent with proc.
In proc, you can check canceler.cancel for truthiness after any use
of await.
If canceler.cancel is truthy, it is guaranteed that a future call to
proc will occur, giving you a chance to return early from this call.
If canceler.cancel is falsy, it is guaranteed that any future call to
proc will be preceded by a future call to init, and this guarantee
lasts until the next await or until this call returns.
canceler.cancel always starts off falsy, and if you never use
await, it will stay falsy, so you can ignore it entirely.
f will forward its parameters to both init and proc as the second
and subsequent parameters, after the initial canceler parameter.
Any exceptions thrown by init or proc will be ignored.
Any Promises returned by init or proc will be awaited,
and any rejections will be ignored.
f will never throw any exceptions.
The Promise returned by f will always resolve to undefined and
never be rejected.
5.7. sst.fetch
import {} from "./sst/catalog/fetch.mjs";
sst.fetch(resource, [options])
The sst.fetch function is a wrapper around the standard
fetch function that provides additional functionality.
The behavior is the same as the standard fetch function, except
the options parameter additionally supports the following options:
insecure(optional)-
If this is truthy and the request would use HTTPS, then HTTPS certificate validation will be skipped. However, this is only supported in Node.js, and the node-fetch package must be available. If the code is running in a browser, then an Error will be thrown, as HTTPS certificate validation cannot be skipped in a browser.
If this is falsy or the request would use HTTP, then there is no effect, even if the code is running in a browser.
By default, this is falsy.
5.8. The sst.fetch_slurp function
sst.fetch_slurp(url, init)
The sst.fetch_slurp function is similar to the fetch
method, but performs multiple requests to gather multiple responses
linked together by the Link header.
5.9. sst.in_browser
import {} from "./sst/catalog/in_browser.mjs";
sst.in_browser()
The sst.in_browser function returns true if the code is running
inside a browser, or false if not.
5.10. sst.is_stream_writable
import {} from "./sst/catalog/is_stream_writable.mjs";
sst.is_stream_writable(x)
The sst.is_stream_writable function returns true if x
implements the stream.Writable interface,
or false if not.
This function has the following advantages over trying to write
x instanceof stream.Writable:
5.11. sst.post_json
import {} from "./sst/catalog/post_json.mjs";
sst.post_json(resource, body, [options={}])
The sst.post_json function is a wrapper around the
sst.fetch function that is streamlined for POST endpoints
that use JSON for both the request body and the response body.
The behavior is the same as sst.fetch(resource, options), but
with the following changes:
-
If
options.bodyis omitted, thensst.json.dump(body)will be used. Otherwise,bodywill be ignored. -
If
options.headersis omitted or is missingContent-Type, thenContent-Type: application/jsonwill be added. -
If
options.methodis omitted, thenPOSTwill be used. -
The returned
Promisewill resolve to the response body parsed as JSON. -
The returned
Promisewill be rejected if the response code is not in the 200-299 range. In this case, the rejectionErrorwill include theResponseas a member namedresponse.
5.12. The sst.sankey function
sst.sankey(edges[, options])
The sst.sankey function draws a Sankey diagram and returns it
as an SVG element.
A Sankey diagram is fundamentally a visualization of a weighted directed
graph.
As such, the minimum information from which a Sankey diagram can be
created is the set of edges of the graph.
The set of edges can be passed in via the edges parameter as an array
of triples, where each triple [A,B,W] means there is an edge from node
A to node B with weight W.
A and B should be strings, and W should be a number.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="d3.js"></script>
<script src="d3-sankey.js"></script>
</head>
<body>
<script type="module">
import {} from "./sst/catalog/sankey.mjs";
const edges = [
["A", "X", 4],
["A", "Y", 1],
["B", "X", 2],
["B", "Y", 3],
];
document.body.appendChild(sst.sankey(edges));
</script>
</body>
</html>
5.12.1. options reference
height-
Specifies the height, in pixels, of the diagram.
The default value is
480. showNodeWeights-
Specifies whether the default node label will display the weight of the node.
The default value is
false. width-
Specifies the width, in pixels, of the diagram.
The default value is
640.
5.13. sst.dom.bootstrap5.progress_bar
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="bootstrap-5.3.3.min.css">
<link rel="stylesheet" href="sst/catalog/dom/bootstrap5/progress_bar.css">
</head>
<body>
<script type="module">
import {} from "./sst/catalog/dom/bootstrap5/progress_bar.mjs";
const v = 25;
const progress_bar = new sst.dom.bootstrap5.progress_bar({
max: 100,
value: v,
});
document.body.appendChild(progress_bar.container());
progress_bar.container().classList.add("m-2");
const label_1 = "Set to 100%";
const label_2 = "Set to " + v + "%";
const full_button = document.createElement("button");
full_button.type = "button";
full_button.classList.add("btn", "btn-primary");
full_button.innerText = label_1;
full_button.addEventListener("click", () => {
if (progress_bar.percent() < 100) {
progress_bar.percent(100);
full_button.innerText = label_2;
} else {
progress_bar.percent(v);
full_button.innerText = label_1;
}
});
document.body.appendChild(full_button);
const spinning_button = document.createElement("button");
spinning_button.type = "button";
spinning_button.classList.add("btn", "btn-primary");
spinning_button.innerText = "Toggle spinning";
spinning_button.addEventListener("click", () => {
const x = progress_bar.spinning();
progress_bar.spinning(!x);
});
document.body.appendChild(spinning_button);
</script>
</body>
</html>
5.14. sst.dom.bootstrap5.text_input
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="bootstrap-5.3.3.min.css">
<link rel="stylesheet" href="sst/catalog/dom/bootstrap5/text_input.css">
</head>
<body>
<script type="module">
import {} from "./sst/catalog/dom/bootstrap5/text_input.mjs";
function create_button(text, callback) {
const button = document.createElement("button");
button.type = "button";
button.classList.add("btn", "btn-primary", "mt-2", "me-1");
button.innerText = text;
button.addEventListener("click", callback);
return button;
}
function create_demo(overlay) {
let options = {
label: "Value",
validator: value => {
if (value === "") {
return "Value must not be empty";
}
},
};
options = Object.assign(options, overlay);
const container = document.createElement("div");
container.classList.add("m-2", "mb-4");
const input = new sst.dom.bootstrap5.text_input(options);
container.appendChild(input.container());
container.appendChild(create_button("Disable", event => {
const b = !input.disabled();
input.disabled(b);
event.target.innerText = b ? "Enable" : "Disable";
}));
container.appendChild(create_button("Commit", event => {
const b = !input.committed();
input.committed(b);
event.target.innerText = b ? "Decommit" : "Commit";
}));
container.lastChild.classList.remove("me-1");
document.body.appendChild(container);
}
create_demo({});
create_demo({
multiline: true,
});
document.body.lastChild.classList.remove("mb-4");
</script>
</body>
</html>
5.15. sst.dom.sidebar
import {} from "./sst/catalog/dom/sidebar.mjs";
class sst.dom.sidebar
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="sst/catalog/dom/sidebar.css">
</head>
<body>
<script type="module">
import {} from "./sst/catalog/dom/sidebar.mjs";
const container = document.createElement("div");
document.body.appendChild(container);
container.style.setProperty("display", "flex");
const sidebar = new sst.dom.sidebar();
container.appendChild(sidebar.container());
sidebar.container().style.setProperty("flex-basis", "15em");
sidebar.container().style.setProperty("flex-shrink", "0");
sidebar.content().innerText = "Sidebar";
const content = document.createElement("div");
container.appendChild(content);
content.innerText = "Content ".repeat(2000);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="sst/catalog/dom/sidebar.css">
</head>
<body>
<script type="module">
import {} from "./sst/catalog/dom/scrollspy.mjs";
import {} from "./sst/catalog/dom/sidebar.mjs";
const container = document.createElement("div");
document.body.appendChild(container);
container.style.setProperty("display", "flex");
const sidebar = new sst.dom.sidebar();
container.appendChild(sidebar.container());
sidebar.container().style.setProperty("flex-basis", "15em");
sidebar.container().style.setProperty("flex-shrink", "0");
const ul = document.createElement("ul");
sidebar.content().appendChild(ul);
const sections = document.createElement("div");
container.appendChild(sections);
const items = [];
for (let i = 0; i < 10; ++i) {
const section = document.createElement("div");
sections.appendChild(section);
section.style.setProperty("flex-grow", "1");
const title = document.createElement("h2");
section.appendChild(title);
title.innerText = "Section " + (i + 1);
const content = document.createElement("div");
section.appendChild(content);
content.innerText = "Content ".repeat(200);
const li = document.createElement("li");
ul.appendChild(li);
li.innerText = title.innerText;
items.push({
getBoundingClientRect: function() {
return section.getBoundingClientRect();
},
li: li,
});
}
sst.dom.scrollspy(items, (active, inactive) => {
for (const item of active) {
item.li.style.setProperty("font-weight", "bold");
}
for (const item of inactive) {
item.li.style.removeProperty("font-weight");
}
});
</script>
</body>
</html>
5.16. sst.dom.list
import {} from "./sst/catalog/dom/list.mjs";
class sst.dom.list
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="sst/catalog/dom/list.css">
</head>
<body>
<script type="module">
import {} from "./sst/catalog/dom/list.mjs";
const container = document.createElement("div");
document.body.appendChild(container);
const list = new sst.dom.list();
let count = 0;
for (; count < 5; count) {
list.add().content().innerText = "Item " + count;
}
const add_button_div = document.createElement("div");
container.appendChild(add_button_div);
const add_button = document.createElement("button");
add_button_div.appendChild(add_button);
add_button.innerText = "Add item";
add_button.addEventListener("click", () => {
const n = list.size();
const i = Math.round(Math.random() * n);
list.add(i).content().innerText = "Item " + count;
});
const remove_button_div = document.createElement("div");
container.appendChild(remove_button_div);
const remove_button = document.createElement("button");
remove_button_div.appendChild(remove_button);
remove_button.innerText = "Remove item";
remove_button.addEventListener("click", () => {
const n = list.size();
if (n > 0) {
const i = Math.floor(Math.random() * n);
list.remove(i);
}
});
const move_button_div = document.createElement("div");
container.appendChild(move_button_div);
const move_button = document.createElement("button");
move_button_div.appendChild(move_button);
move_button.innerText = "Move item";
move_button.addEventListener("click", () => {
const n = list.size();
if (n > 1) {
const i = Math.floor(Math.random() * n);
let j;
do {
j = Math.round(Math.random() * n);
} while (i === j || i === j - 1);
list.move(i, j);
}
});
container.appendChild(list.container());
</script>
</body>
</html>
5.17. sst.dom.hideable
import {} from "./sst/catalog/dom/list.mjs";
class sst.dom.hideable
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="sst/catalog/dom/hideable.css">
</head>
<body>
<script type="module">
import {} from "./sst/catalog/dom/hideable.mjs";
const container = document.createElement("div");
document.body.appendChild(container);
const hideable = new sst.dom.hideable();
hideable.content().innerText = "Hideable content";
const button_div = document.createElement("div");
container.appendChild(button_div);
const button = document.createElement("button");
button_div.appendChild(button);
button.innerText = "Hide";
button.addEventListener("click", () => {
if (hideable.hidden()) {
hideable.hidden(false);
button.innerText = "Hide";
} else {
hideable.hidden(true);
button.innerText = "Unhide";
}
});
container.appendChild(hideable.container());
</script>
</body>
</html>
5.18. sst.reduce_motion
import {} from "./sst/catalog/reduce_motion.mjs";
sst.reduce_motion()
The sst.reduce_motion function returns true if motion
should be reduced in the user interface, or false if not.
This value may change over time.
In a browser, this function returns true if the current value of
the prefers-reduced-motion media feature is reduce, or
false if not.
6. CMD library
6.1. The sst_find_java_home function
sst_find_java_home
The sst_find_java_home function finds the best JAVA_HOME
directory on the system.
If the function exits with error level 0, then JAVA_HOME will have
been set appropriately in the calling context.
6.2. The sst_find_java function
sst_find_java
The sst_find_java function finds the best java executable on
the system.
If the function exits with error level 0, then JAVA will have been set
appropriately in the calling context.
7. jq library
7.1. The sst_assert function
sst_assert($x; $message)
The sst_assert function calls error($message) if $x
is a value other than false or null.
Otherwise, the function produces its input unchanged.
7.2. The sst_nwise function
sst_nwise($n)
The sst_nwise function splits an array into partitions of size
$n and outputs the partitions in an array.
$n must be a positive integer.
If the input array is empty, the result is an empty array.
If the input array does not contain a multiple of $n elements, the
last partition will only contain the last length % $n
elements.
7.3. The sst_adjacent_pairs function
The sst_adjacent_pairs function enumerates all adjacent pairs of
elements of an array and outputs the pairs in an array.
If the input array has fewer than two elements, the output array will be empty.
7.4. The sst_graphviz_escape function
The sst_graphviz_escape function escapes a string for use in Graphviz,
without surrounding it with quotes.
7.5. The sst_graphviz_quote function
The sst_graphviz_quote function escapes a string for use in Graphviz,
including surrounding it with quotes.